Rails MemcachedStore for the Memcached Gem
I’ve been experimenting with the memcached gem (the c gem that runs up to 150x faster than memcache-client). Merb already has pretty good support for the Memcached gem and in typical merb style does it better with fewer lines of code but I digress. Here’s my test implementation, so far so good nothing really heavy on it yet. YMMV so be warned this is not tested in a production environment don’t say I didn’t warn you so and such.
# in your environment file
config.cache_store = :memcached_store, 'localhost:11211'
# lib/memcached_store.rb
require 'memcached'
module ActiveSupport
module Cache
class MemcachedStore < Store
attr_reader :addresses
def initialize(*addresses)
addresses = addresses.flatten
options = addresses.extract_options!
addresses = ["localhost"] if addresses.empty?
@addresses = addresses
@data = Memcached::Rails.new(addresses, options)
end
def read(key, options = nil)
super
@data.get(key, raw?(options))
rescue Memcached::Error => e
logger.error("Memcached::Error (#{e}): #{e.message}")
nil
end
# Set key = value. Pass :unless_exist => true if you don't
# want to update the cache if the key is already set.
def write(key, value, options = nil)
super
method = options && options[:unless_exist] ? :add : :set
response = @data.send(method, key, value, expires_in(options), raw?(options))
response == nil
rescue Memcached::Error => e
logger.error("Memcached::Error (#{e}): #{e.message}")
false
end
def delete(key, options = nil)
super
response = @data.delete(key, expires_in(options))
response == nil
rescue Memcached::Error => e
logger.error("Memcached::Error (#{e}): #{e.message}")
false
end
def exist?(key, options = nil)
# Doesn't call super, cause exist? in memcache is in fact a read
# But who cares? Reading is very fast anyway
!read(key, options).nil?
end
def increment(key, amount = 1)
log("incrementing", key, amount)
@data.incr(key, amount)
rescue Memcached::Error
nil
end
def decrement(key, amount = 1)
log("decrement", key, amount)
@data.decr(key, amount)
rescue Memcached::Error
nil
end
def delete_matched(matcher, options = nil)
super
raise "Not supported by Memcache"
end
def clear
@data.flush_all
end
def stats
@data.stats
end
private
def expires_in(options)
(options && options[:expires_in]) || 0
end
def raw?(options)
options && options[:raw]
end
end
end
end
Snippet
Thoughts on User.current and Thread Safety

Pratik Naik has an interesting post Thread safety for your Rails about what thread safety in Rails means (and what it doesn’t). One of the interesting points is that a common pattern of using class attributes is not thread safe and can lead to race conditions. I found it interesting because I’m a big proponent of User.current. I’ve always gotten great millage out of it and I’ve always felt like it’s a necessary evil for protecting user_id attributes from mass assignment and not totally driving yourself nuts with @foo.user_id = session[:user_id] all over your controller actions.
So the problem now is that if you ever intend to use User.current with a thread safe Rails app you’ve got to adjust fire. My thoughts are now turned toward investigating the following.
class ApplicationController < ActionController::Base
before_filter :current_user_id
# Set the value
def current_user_id
Thread.current[:current_user_id] = session[:user_id]
end
end
class User < ActiveRecord::Base
def self.current
Thread.current[:current_user] ||= self.fetch_by_id(Thread.current[:current_user_id])
end
end
Snippet
This seems like a thread safe method of accessing the current User without trading off the real functionality we want.
Slicehost Acquired by Rackspace
In case you’ve had your head in the sand the technology world is abuzz with hype about “the cloud”. Last week Rackspace had there own little cloud announcement and I was grimacing with the thought of yet another large host entering the fray. In case you don’t know I’m not a huge fan of “the cloud,” so I was imagining Rackspace might introduce yet another subpar on demand computing service. I couldn’t have been more wrong as it turns out. Rackspace wasn’t introducing a new unprove service, they were acquiring a proven leader already well respected in the industry, Slicehost.
Slicehost has been around for a few years now and has had such demand in the beginning I was on a waiting list. It was worth it because the service has been great. I’ve been hosting Snippy for a little while now on it and a few other things and I’m very happy. I’ve also had really great luck with Rackspace in the past so to hear that they were going to be adding their financial support and letting Slicehost run as a subsidiary is a awesome.
Slicehost will be able to keep it’s great level of support and is already lowering the pricing on some of their existing slices. Check them out if you’re looking for rails hosting, they’‘re well worth it.


