Reputation: 5558
I have a pretty slow controller action, which does some raporting here and there. I only need to refresh the data every few days, so it was no brainer to static cache the result.
The problem is, that the action takes solid few minutes to complete and I am not sure whats the most optimal way to expire the old data and replace them with the new ones.
Now the problem with just generic expire/request is that for few minutes (time when the action is running) those data are unavailable.
Is there any resonable way to overcome this gap using just static cache mechanisms in Rails? Or should I just rebuild the whole thing in a different way?
Upvotes: 0
Views: 981
Reputation: 10856
Rails has a built-in way to use stale caches for just a bit longer when it expires while the new cache value is being regenerated. It's the :race_condition_ttl
setting used in conjuction with :expires_in
, as describe in the Rails Guides on Caching.
With Rails Fragment caching the syntax should be:
<% cache 'my_awesome_cache_key', :expires_in => 12.hours.to_i, :race_condition_ttl => 12.hours.to_i %>
# This block will be cached
<% end %>
Results:
race_condition_ttl
was introduced to prevent multiple processes from regenerating a cache simultaneuosly, which would result in all processes reading the data from the db at once etc. on a highly requested resource, but I think it should work well for your situation.
How to choose the timing for :expires_in
and :race_condition_ttl
is your choice then, I'd suggest calculating it like this: expires_in + race_condition = expires_in_that_you_would_usually_set
. This way the cache is regenerated more often but also fresher, especially if the action/view is not rendered that often.
Upvotes: 3