Expire cache from BackgroundRB async process?

I'm having some difficulty finding a way to expire the cache after executing an asynchronous BackgroundRB task. From a Rails controller I fire off an async worker which will handle importing of data from a file and, when completed, the fragment cache of a page needs to be expired. I've tried ...

1. Simply calling expire_action from within the BackgroundRB worker. However, it appears that BackgroundRB doesn't have access to ActionController.

2. Using sweepers/observers on the model object being changed by the BackgroundRB worker. The BackgroundRB worker will do some stuff with the model object, the observer will catch this, and the sweeper will handle expiring the cache. However, the sweeper complains that the record passed to the after_whatever callback methods is nil. Without this model object I can't expire the correct cache.

Using Rails 2.1 and the absolute latest BackgroundRB from github.

Any suggestions?

Cheers, Justin

Hi Justin.

I've had the same problem in my application. I need to expire cache fragments after completing a rake task.

It seems to be no way to call sweepers/observers from outside the controller, so I did this little trick:

In one of my controllers I created a public method:

def expire_my_fragments   expire_fragment('') end

then in the rake task I've added in the bottom of the method:

task :start_my_custom_task => :environment do     do_something()     require 'action_controller/integration'     app = ActionController::Integration::Session.new     app.get('/my_controller/expire_my_fragments') end

As you can see, I call an integration test after the end of my task. Finally, if you want that the integration test expires your fragments, you need to invoke your task with production environment parameters:

rake environment RAILS_ENV=production start_my_custom_task

I hope you find this useful.

Cheers, Stefano

Justin Britten wrote:

I'm having some difficulty finding a way to expire the cache after executing an asynchronous BackgroundRB task. From a Rails controller I fire off an async worker which will handle importing of data from a file and, when completed, the fragment cache of a page needs to be expired. I've tried ...

1. Simply calling expire_action from within the BackgroundRB worker. However, it appears that BackgroundRB doesn't have access to ActionController.

2. Using sweepers/observers on the model object being changed by the BackgroundRB worker. The BackgroundRB worker will do some stuff with the model object, the observer will catch this, and the sweeper will handle expiring the cache. However, the sweeper complains that the record passed to the after_whatever callback methods is nil. Without this model object I can't expire the correct cache.

Using Rails 2.1 and the absolute latest BackgroundRB from github.

Any suggestions?

Cheers, Justin

Have you tried using Rails.cache.delete(cache_path) from the model?

The sweepers weren't fine-grained enough for my fragment caching, and I ended up just taking control of the cache expiration (for my app, a single model may have, oh, 8 different fragments cached, and it may appear in cache fragments of any number of other models -- polymorphic relationships are cool, but have their downside -- so depending on what changed, a model knows what caches it should expire of its own, and if fragments of models it has a relationship with should expire also - i.e., my name field changed and that other model's cache shows my name).

The problem is that the model object doesn't seem to be available to the callback function.

For example, in the sweeper: observe MyModel

def after_create(record)   expire the cache end

And, in the BackgroundRB worker: MyModel.create()

And when the BackgroundRB async task is started, the MyModel after_create() method is invoked as expected; however, record is nil (as is self).

The record has some info in it that I use to calculate the path to expire. So, I can't call Rails.cache.delete(cache_path) when I can't determine the value of cache_path.

Thanks for taking the time to help, Justin

Ar Chron wrote:

Justin Britten wrote:

The problem is that the model object doesn't seem to be available to the callback function.

For example, in the sweeper: observe MyModel

def after_create(record)   expire the cache end

And, in the BackgroundRB worker: MyModel.create()

And when the BackgroundRB async task is started, the MyModel after_create() method is invoked as expected; however, record is nil (as is self).

The record has some info in it that I use to calculate the path to expire. So, I can't call Rails.cache.delete(cache_path) when I can't determine the value of cache_path.

Thanks for taking the time to help, Justin

If there's something wrong with BackgroundRB and sweepers, have you tried:

In the BackgroundRB worker:

  my_model = MyModel.create(blah blah blah)   my_model.clear_the_cache

and inside MyModel

  def clear_the_cache     Rails.cache.clear(cache_path from data)   end

AR.create *should* be handing back a model, which could self-inspect to derive the cache path to expire...