Skip to content

Instantly share code, notes, and snippets.

@showell
Created December 2, 2010 19:41
Show Gist options
  • Save showell/725923 to your computer and use it in GitHub Desktop.
Save showell/725923 to your computer and use it in GitHub Desktop.
using memcache to cache results of expensive functions with a URL scheme
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
@showell
Copy link
Author

showell commented Dec 2, 2010

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment