Last active
August 29, 2015 14:02
-
-
Save andrewberls/60cc7cf0a655570012b2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# lib/cache_proxy.rb | |
class CacheProxy | |
class << self | |
attr_accessor :cache | |
end | |
def initialize(obj) | |
@obj = obj | |
end | |
def cache_key(meth) | |
"#{self.class}:#{@obj.class}:#{@obj.object_id}:#{meth}" | |
end | |
def cache_fetch(meth, *args, &block) | |
key = cache_key(meth) | |
self.class.cache.cache_fetch(key, expires_in: 1.hour) do | |
@obj.__send__(meth, *args, &block) | |
end | |
end | |
def method_missing(meth, *args, &block) | |
if @obj.respond_to?(meth) | |
cache_fetch(meth, *args, &block) | |
else | |
super | |
end | |
end | |
end | |
module CacheProxyMethods | |
def cached | |
CacheProxy.new(self) | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# config/initializers/cache_proxy.rb | |
require 'cache_proxy' | |
ActiveSupport.on_load(:redis) do | |
CacheProxy.cache = $redis | |
ActiveRecord::Base.send(:include, CacheProxyMethods) | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# config/initializers/redis.rb | |
$redis = Redis.new | |
class << $redis | |
# Include client helper extensions, which implement cache_fetch among others | |
include RedisClientExtensions | |
end | |
ActiveSupport.run_load_hooks(:redis, self) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module RedisClientExtensions | |
# Get/set a value cached in a key | |
# | |
# key - String key name | |
# expires_in: Integer TTL of the key, in seconds | |
# block - Proc to compute the value to be cached on miss | |
# | |
# Returns result of evaluating <block> | |
def cache_fetch(key, expires_in:, &block) | |
if ret = get(key) | |
ret | |
else | |
val = block.call | |
set(key, val) | |
expire(key, expires_in) | |
val | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
An experiment to transparently cache methods independent of their implementation. Example:
Calling
cached
on an object will return a corresponding CacheProxy:Calling methods on this cache proxy will first check the cache for a value, and only call the actual method if a value is missing. Note this is accomplished using the
cache_fetch
method on the configurable cache backend, which is responsible for implementing this (we've added thecache_fetch
method to the Redis client, although any interface that implementscache_fetch
will do)