Created
December 2, 2010 19:41
-
-
Save showell/725923 to your computer and use it in GitHub Desktop.
using memcache to cache results of expensive functions with a URL scheme
This file contains 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
class CacheCall | |
# Calls a function that accepts a hash as its only parameter UNLESS | |
# the result has been recently cached. Cache keys are essentially a | |
# URL of the hash keys and values. | |
# | |
# ====Parameters | |
# | |
# +method_obj+:: | |
# A Ruby method object that supports call() and .name | |
# | |
# +options+:: | |
# A hash of options that servers two purposes: | |
# 1) uniquely identifies the resource or results we seek | |
# 2) can be passed into into method_obj.call() | |
# | |
# +last_updated+:: | |
# The last time the resource was updated. If we don't care about current | |
# values, just make this far in the past. | |
# | |
# +expiry+:: | |
# number of seconds that we want the item to stay in the cache | |
# | |
# ====Returns | |
# | |
# Returns the results of the method_obj.call() UNLESS we already | |
# have a value in the cache that is more recent than last_updated. | |
def CacheCall.cache_call(method_obj, options, last_updated, expiry=nil) | |
cache_key = CacheCall.url(method_obj.name, options) | |
if cache_key.size > RANGER_CONFIG[:max_cache_key_size] | |
cache_key = Digest::SHA1.hexdigest(cache_key) | |
end | |
expiry ||= RANGER_CONFIG[:default_cache_expiry] | |
Cache.timestamped_get( | |
cache_key, | |
last_updated, | |
expiry | |
) do | |
method_obj.call(options) | |
end | |
end | |
# Returns a URL-like representation of a function call. | |
# (Think in terms of functions having a REST-like API that allows | |
# callers to cache results.) | |
# | |
# ====Parameters | |
# | |
# +method_name+:: | |
# The name of a method. | |
# | |
# +options+:: | |
# A hash of keys and values. Values should be simple scalars or | |
# ActiveRecord objects. We may expand this to handle other types of | |
# objects in the future. | |
# | |
# ====Returns | |
# | |
# Returns a string like this: | |
# search_results_dec_2010/limit=10/offset=0/search_string=city/user_id=1/viewer_id=1 | |
# | |
def CacheCall.url(method_name, options) | |
keys = options.keys.sort_by { |key| key.to_s } | |
url = method_name | |
for key in keys do | |
val = options[key] | |
key = key.to_s | |
if !val.nil? | |
if val.kind_of?(ActiveRecord::Base) | |
key += "_id" | |
val = val.id | |
else | |
val = CGI::escape(val.to_s) | |
end | |
url += "/#{key}=#{val}" | |
end | |
end | |
return url | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is not packaged up for immediate use...it's more of a proof of concept. The CacheCall.url method only depends on ActiveRecord and CGI.