Skip to content

Loading…

Gracefully degrade when cache store goes offline #66

Merged
merged 1 commit into from

4 participants

@alau

This fixes issue #42.

When storing a response in MetaStore#store, the cached response body is read
back and subsequently used as response body. If the cache store is offline then
the read-back value may be nil. In that case, the store operation overwrites a
valid response body with nil.

We noticed this problem when we temporarily took down memcached during
maintenance. We expected the site to slow down, but cached pages instead became
empty.


The idea of the implementation is to only overwrite the response body if we get
a hit when reading back the body from the cache. The aim is to change as little
code as possible. I do not understand the code base, so there are probably many
assumptions that I am not aware of.

The test creates new stores that implement all(?) abstract methods with
versions that mimic an offline store and then tries to store a value. I'm
unsure whether the preferred style is to define the classes inside or outside
the examples.

Other tests explicitly check that the response body is not the same after
calling #store. I'm assuming that this is because we want to use IO-streams or
something from the backing store, and that it does not apply in this case. I am
unsure though, and would like some feedback on that.

Feedback is more than welcome

@alau alau Gracefully degrade when cache store goes offline
The metastore reads back the cached body after storing it. If the cache
store is offline (e.g. memcached goes down) then the value read back
will be nil. This commit falls back to the original body when that
happens.
fcb3fbb
@Mange

*subscribing*

@rtomayko
Owner

Looks great. Thanks!

@rtomayko rtomayko merged commit b4f8ce9 into rtomayko:master
@grosser
Collaborator

@rtomayko can you release that ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 29, 2012
  1. @alau

    Gracefully degrade when cache store goes offline

    alau committed
    The metastore reads back the cached body after storing it. If the cache
    store is offline (e.g. memcached goes down) then the value read back
    will be nil. This commit falls back to the original body when that
    happens.
This page is out of date. Refresh to see the latest.
Showing with 21 additions and 1 deletion.
  1. +1 −1 lib/rack/cache/metastore.rb
  2. +20 −0 test/metastore_test.rb
View
2 lib/rack/cache/metastore.rb
@@ -64,7 +64,7 @@ def store(request, response, entity_store)
end
response.headers['X-Content-Digest'] = digest
response.headers['Content-Length'] = size.to_s unless response.headers['Transfer-Encoding']
- response.body = entity_store.open(digest)
+ response.body = entity_store.open(digest) || response.body
end
# read existing cache entries, remove non-varying, and add this one to
View
20 test/metastore_test.rb
@@ -182,6 +182,26 @@ def self.call(request); request.path_info.reverse end
@store.lookup(@request, @entity_store).should.be.nil
end
+ it 'gracefully degrades if the cache store stops working' do
+ @store = Class.new(Rack::Cache::MetaStore) do
+ def purge(*args); nil end
+ def read(*args); [] end
+ def write(*args); nil end
+ end.new
+ @entity_store = Class.new(Rack::Cache::EntityStore) do
+ def exists?(*args); false end
+ def open(*args); nil end
+ def read(*args); nil end
+ def write(*args); nil end
+ def purge(*args); nil end
+ end.new
+
+ request = mock_request('/test', {})
+ response = mock_response(200, {}, ['test'])
+ @store.store(request, response, @entity_store)
+ response.body.should == ['test']
+ end
+
# Vary =======================================================================
it 'does not return entries that Vary with #lookup' do
Something went wrong with that request. Please try again.