module Mozo module Counter extend ActiveSupport::Autoload autoload :Redis mattr_accessor :connection # mainly for testing purposes def self.set(key, value) connection.set(key, value) rescue value end def self.get(key) connection.get(key, quiet: true).to_i rescue 0 end def self.incr(key, options = {}) options[:initial] ||= 1 connection.incr(key, options) rescue 1 end def self.decr(key, options = {}) options[:initial] ||= 0 connection.decr(key, options) rescue 0 end # Provision Redis counters from CouchDB aggregated data. # Reads the Order.by_supplier_id_and_state view (reduce, grouped), # and sets the corresponding Redis keys. # # Invoke via: rails runner 'Mozo::Counter.provision!' # def self.provision! require 'couchrest' # CouchPotato::Database wraps CouchRest — get the raw DB for direct view queries db = Order.database.couchrest_database design = '_design/order_counter' view = 'by_supplier_id_and_state' # Ensure the design doc exists (auto-create if missing) begin db.get(design) rescue RestClient::ResourceNotFound, CouchRest::NotFound puts "[Counter.provision!] Creating design doc #{design}" doc = YAML.safe_load(File.read(Rails.root.join('drb_counter/couchdb_design.yml'))) doc['_id'] = design doc['language'] ||= 'javascript' db.save_doc(doc) end # Query with reduce + group to get per-supplier/per-state counts result = db.view("#{design}/_view/#{view}", reduce: true, group: true, group_level: 2) rows = result['rows'] || [] puts "[Counter.provision!] #{rows.size} counter keys to set" rows.each do |row| supplier_id, state = row['key'] count = row['value'] key = case state when 'placed' then "supplier_counter:#{supplier_id}:orders_placed" when 'active' then "supplier_counter:#{supplier_id}:orders_in_process" end next unless key set(key, count) puts " #{key} = #{count}" end puts "[Counter.provision!] Done." rows.size end end end