0

I have a Rails app that includes some after_save active record callbacks, which are responsible for updating a second cache database.

Recently I was having some load issues and the second database was slow to respond or refusing connections, and my users started getting 500 errors when they tried to save objects.

I think this was down to me misunderstanding how callbacks work - I assumed that by making these after_save rather than before_save, the user was "safe" and if the callback failed, that would be graceful and silent.

How might I refactor my code to stop this behaviour and avoid exposing my users to error messages when these callbacks fail?

I've looked at refactoring the callbacks to simply trigger an active job, like this:

# models/mymodel.rb

after_save :update_index

def update_index
    UpdateIndexJob.perform_later(self)
end

The active job includes the logic for actually updating the second cache database.

I'm not sure whether I would also need to implement sidekiq and redis for this to work.

I've also read about rails observers, which apparently work similar to callbacks but don't break the request-response cycle when they fail.

parasomnist
  • 178
  • 1
  • 12

1 Answers1

0

How can I stop active record callbacks from throwing an error when they fail?

That's a very open question, and I think you've already answered it yourself.

You can either:

  1. Rewrite it in such a way that it won't fail (e.g. only invoke a background task).
  2. Rescue the exception. (But then, is aborting that path of the code actually a sensible decision?! Probably not.)

I've looked at refactoring the callbacks to simply trigger an active job [...] I'm not sure whether I would also need to implement sidekiq and redis for this to work.

That seems like a safe implementation. And yes, you will need to configure a backend in order to actually execute the jobs. See the documentation. Sidekiq, Resque, Sneakers, Sucker Punch, Queue Classic, Delayed Job and Que are just some of the available choices.

I've also read about rails observers ...

That would also prevent user errors, but what happens if it fails due to an intermittent timeout?? One of the core features of background jobs is that they retry on failure.

Therefore I would advise using a background job instead of an observer for this.


Now with all of that said, we've barely spoken about what problem you're trying to solve:

updating a second cache database

You've said very little able what the "second cache database" actually is, but I suspect this could actually be configured as a leader/follower database, and live completely outside of your application.

Tom Lord
  • 27,404
  • 4
  • 50
  • 77