Fragment caching keeping stale product prices

I’ve got a list of products in my system and a master list of products
available from my distributor. Every night I import a new
distributor product file and update the prices for my list of products
if any of them have changed.

The code to import the new distributor catalog file runs from a rake
task in my crontab and all of my products/show pages are cached, as
well as my index pages, so after updating all the prices, the system
still displays the old cached price.

I need to be able to expire the cache fragments from one of the models
that deals with downloading and importing the new distributor catalog
file, but as far as I can tell, it’s not possible to execute the cache
expiration methods from a model. Is there any way I can manually
expire these caches? Or call my cache_sweeper from the model? My
ProductSweeper looks something like this:

def after_save(product)
expire_fragment(product_path(product))
#expire some more stuff here…
end

The other option is to not cache the product price, which will require
me to go through all my code and end my cache blocks before the price
is displayed, then start the cache block afterwards, but I’d have to
use two separate cache names, like ‘product_info_top’ and
‘product_info_bottom’, which starts to get messy and something I
wanted to avoid. I can’t find any sort of “no_cache” specifier to
wrap around a value in a cached block… Would be very useful…

So I’m wondering if anyone has any advice or suggestions… Thanks in
advance for your help!

def after_save(product)
expire_fragment(product_path(product))
#expire some more stuff here…
end

Are you sure the

expire_fragment(product_path(product))

is expiring the same location that the

cache(whatever) do

is writing to?

Been there, done that. :frowning:

I believe so… I’m using:

<% cache(product_path(@product)) do -%>
cached version of product info
<% end %>

and in my sweeper:

expire_fragment(product_path(product))

they should both refer to the same location, no?

On Fri, May 30, 2008 at 11:42 AM, Ar Chron

The issue might be that the import isn’t going through the normal route
that would cause the sweeper to be invoked (no pass through the
controller?).

What if you scrap the cached fragment manually in your import when you
know you’re writing a new price? (Don’t know how your import works, so
this is just a wag…)

On Fri, May 30, 2008 at 5:10 PM, Ar Chron
[email protected] wrote:

The issue might be that the import isn’t going through the normal route
that would cause the sweeper to be invoked (no pass through the
controller?).

What if you scrap the cached fragment manually in your import when you
know you’re writing a new price? (Don’t know how your import works, so
this is just a wag…)

that’s the question. How do you expire a fragment cache manually
without going through the controller? My import method is in a model
which is called from a rake task. It loops through all the products
who’s prices have changed and updates them. But I have no way of
invalidating the cache. I’ve now changed my caches so I exclude the
price from the cache, but it’s pretty ugly. I’d love to be able to
manually expire the cache from my import model. I can expire a file
based cache easily by using FileUtils.rm_r, but I don’t know how to do
this with the default memory based cache which is used on my
production machine. Thanks