Delayed Job is a popular gem for running background tasks on Rails applications. Apartment is another useful gem for switching Postgresql schemas in response to particular subdomains (it means that visiting ibm.myapp.com will automatically switch to the ‘ibm’ schema and select * from user will only return IBM users).
What’s the problem?
Getting these two gems to play well together can be a little difficult because DelayedJob has no idea how to handle postgres schemas. In a nutshell, DelayedJob serialises the job and parameters as a YAML string in the database column. However, if one of these parameters (or the job) is an ActiveRecord object it will try to reload this from the database… but it will fall over because those objects are not in the same schema as the
Luckily the Apartment gem has instructions for configuring it to work with DelayedJob. These instructions persist a new
database attribute which is then used to switch schemas inside a DelayedJob hook. Unfortunately, it does require using the
syck YAML parser and whilst this worked for me in development, I couldn’t get it working in production. Also, the default parser in Ruby 1.9.3 is Psych and I’d really rather keep it that way.
What’s a possible the solution?
You could spend a while trying to patch the Psych parser so that it will switch schema automatically as it is reconstructing the ActiveRecord objects from the database. Unfortunately, I wasn’t able to make this work reliably and it made me feel all icky anyway. But it did make me question why we were even persisting AR object inside a delayed_job…
So, what’s the actual solution?
Don’t use ActiveRecord parameters in DelayedJobs.
Just pass in basic scalar types (integer, strings, etc) and arrays, and use these to search for the correct ActiveRecord. It all works considerably easier this way and is much simpler to understand. To be honest, this seems like good practice anyway and I’d prefer if DelayedJob didn’t try to serialise AR records at all. I still use the DelayedJob hooks provided by Apartment to automatically switch database schemas before and after job invocation though because they are simple and reliable.