Topic: [Memcached] deleting group/type of cached keys.

Hey all,

I am using Rails 2.1 with memcached 1.2.2 (Both outdated but upgrading is not an option...)

Right now we are storing a number of html pages for every user.

[:users_home]\["<user_page_id>"]

In the normal Rails cache store we can save it like this

Rails.cache.fetch("users_home_#{user_page_id}") do "html page content"; end

Now we come to our problem. We would like to clear the cache for al pages but not the rest of the cache ofcourse.

So we would like to delete all the users_home_<id> keys for example

"users_home_1"
"users_home_2"
"users_home_3"
"users_home_4"

The user database got 1 million users and every user got more or less 3 pages, so to delete all the users_home_<id> would be a long loop with a lot of deleting with non existed memcached keys

Does somebody has know how it is possible to build the cache like this: [:users_home][:user_page_id]
And to delete your cache like this:

Rails.cache.delete_type(:users_home)

or is it possible to tag memcached keys. For example

 Rails.cache.write('user_page_id', "html content" {:tag => "users_home"} 
Rails.cache.delete_tag('users_home')

Thanks a lot in advanced.

Michael

Last edited by mokkol (2011-02-03 07:56:02)

Re: [Memcached] deleting group/type of cached keys.

If i search in the Rails source i think i need this method:

 Rails.cache.delete_matched 

This is the code for the file_store:

def delete_matched(matcher, options = nil)
        super
        search_dir(@cache_path) do |f|
          if f =~ matcher
            begin
              File.delete(f)
            rescue SystemCallError => e
              # If there's no cache, then there's nothing to complain about
            end
          end
        end
      end

It is just searching the directory and deleting when the regex is matched.

But ofcourse no luck over here because this is the code for memcached store:

  def delete_matched(matcher, options = nil)
     super
     raise "Not supported by Memcache"
   end    

I really really really hope that there is a solution for this problem...

Thanks

Last edited by mokkol (2011-02-03 08:16:59)

Re: [Memcached] deleting group/type of cached keys.

I fixed my problem. Based on a plugin from martincik: https://github.com/martincik/memcache_s … te_matched

Here is the solution.

module ActiveSupport
  module Cache
    class MemCacheStore
            
      def write(name, value, options = nil)
        super
        key_list = get_key_list
        unless key_list.include?(name)
          key_list << name
          return false unless _write("memcached_store_key_list", key_list.to_yaml, options)
        end
        _write(name, value, options)
      end
      
      def delete_type(type, options = nil)
        type = type.to_s if type.is_a?(Symbol)
        matcher = Regexp.new("^#{type}")
        keys_to_remove = []
        key_list = get_key_list
        key_list.each do |key|
          if key.match(matcher)
            # puts "key matched!: #{key.inspect}"
            return false unless delete(key, options)
            keys_to_remove << key
          end
        end
        key_list -= keys_to_remove
        _write("memcached_store_key_list", key_list.to_yaml, options)
      end

      private

      def get_key_list
        begin
          YAML.load(read('memcached_store_key_list'))
        rescue TypeError
          []
        end
      end

      def _write(key, value, options = nil)
        method = options && options[:unless_exist] ? :add : :set
        response = @data.send(method, key, value, expires_in(options), raw?(options))
        return true if response.nil?
        response == Response::STORED
      rescue MemCache::MemCacheError => e
        logger.error("MemCacheError (#{e}): #{e.message}")
        false
      end
    end
  end
end

It still needs some security improvements so watch out if somebody uses it!

Anyways, thanks for the people who have read this thread :-)

Michael

Last edited by mokkol (2011-02-03 12:45:07)