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...