Question

In my production middleware stack in all environments I see this one-off instance:

use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x7f38095d>

I've experimented by removing everything I can think of related to caching, but I'm unable to figure out where it comes from.

What is it?

Was it helpful?

Solution

In the abstract, it wraps another cache with an in-memory cache for the duration of a block, and then is cleared after the block.

In practice I believe it is used in Rails/Rack to wrap whatever cache you have configured (memcached, disk) with an in-memory cache which is cleared at the end of the request. The idea is that if you fetch the same cache key twice in one request, it will be cached in the wrapping LocalCache on the first request and will loaded from memory on the second request (instead of reaching out to the memcached server/disk again).

From the docs:

Caches that implement LocalCache will be backed by an in-memory cache for the duration of a block. Repeated calls to the cache for the same key will hit the in-memory cache for faster access.

Git History: https://github.com/rails/rails/commits/master/activesupport/lib/active_support/cache/strategy/local_cache.rb

RDoc: http://api.rubyonrails.org/classes/ActiveSupport/Cache/Strategy/LocalCache.html

OTHER TIPS

First, I'd like to show you some methods from official document.

ActiveSupport::Cache::DalliStore#with_local_cache

def with_local_cache
  use_temporary_local_cache(LocalStore.new) { yield }
end

def use_temporary_local_cache(temporary_cache)
  save_cache = LocalCacheRegistry.cache_for(local_cache_key)
  begin
    LocalCacheRegistry.set_cache_for(local_cache_key, temporary_cache)
    yield
  ensure
    LocalCacheRegistry.set_cache_for(local_cache_key, save_cache)
  end
end

def write(name, value, options=nil)
  options ||= {}
  name = expanded_key name

  instrument(:write, name, options) do |payload|
    with do |connection|
      options = options.merge(:connection => connection)
      write_entry(name, value, options)
    end
  end
end

def write_entry(key, entry, options) # :nodoc:
  local_cache.write_entry(key, entry, options) if local_cache
  super
end

And now, we use them in practice.

@cache = Rails.cache
@cache.with_local_cache do
   @cache.write('key', 'value')
end

If you combine the code above, you'll find that there should have two place which cached ('key', 'value') pairs. One is LocalCache, another is our @cache. It's purpose is declared in source code clearly.

Caches that implement LocalCache will be backed by an in-memory cache for the duration of a block. Repeated calls to the cache for the same key will hit the in-memory cache for faster access.

I hope this will do help for you!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top