Skip to content

Instantly share code, notes, and snippets.

@alvinsj
Last active December 14, 2015 08:28
Show Gist options
  • Save alvinsj/5058021 to your computer and use it in GitHub Desktop.
Save alvinsj/5058021 to your computer and use it in GitHub Desktop.
redis memoization, sidekiq background job (with unique job)
module Memoize
def remember(klass, method_name)
klass.class_eval do
memory = $redis
original = "original_#{method_name}"
original_method = method(method_name)
define_singleton_method(method_name) do |*args|
key = "#{method_name}:"+args.to_json
if memory[key].nil?
worker_class = "#{self.name}Worker"
if Memoize::Helper.class_defined?(worker_class)
worker_class.constantize.perform_async(method_name, key, *args)
nil
else
result = original_method.call *args
memory[key] = result.to_json
result
end
else
Memoize::Helper.parse(memory[key])
end
end # end define_singleton_method
end # end class_eval
end # end remember
private
module Helper
def self.class_defined?(class_name)
klass = class_name.constantize
return true
rescue NameError
return false
end # end define
def self.parse(value)
value = JSON.parse(value) if value.instance_of?(String)
case
when value.instance_of?(Array)
value = value.map{|v| parse(v) }
when value.instance_of?(Hash)
value.each{|k,v| value[k] = parse(v) }
else
value
end
rescue
return value
end # end def
end # end module
end
class PagesController < ApplicationController
before_action :memoize_methods
private
def memoize_methods
self.class.remember Stats, :count
self.class.remember Stats, :group_count
self.class.remember Stats, :graph_points
end
end
class StatsWorker
include Sidekiq::Worker
sidekiq_options unique: true, unique_job_expiration: 60
def perform(method, key, *args)
result = Stats.send method, *args
$redis[key] = result.to_json unless result.nil?
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment