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' db = Order.database design = '_design/order_counter' view = 'by_supplier_id_and_state' # Ensure the design doc exists unless db.get(design) rescue nil puts "[Counter.provision!] Creating design doc #{design}" doc = YAML.safe_load( File.read(Rails.root.join('drb_counter/couchdb_design.yml')), permitted_classes: [Symbol] ) 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'] case state when 'placed' key = "supplier_counter:#{supplier_id}:orders_placed" when 'active' key = "supplier_counter:#{supplier_id}:orders_in_process" else next end set(key, count) puts " #{key} = #{count}" end puts "[Counter.provision!] Done." rows.size end end end