I’m hard at work on iEye these days.
To take care of images, we use Paperclip, and are loving it. But according to New Relic’s RPM, the slowest part is when we upload a image, and it creates a few different versions (not that it was any surprise that that was slow). I searched a bit around for a easy way to make Paperclip work with delayed_job, but soon concluded that I would have to do it myself. Which I did.
The first step was to create a small wrapper-class for my model. I’m attaching images to a
Image-model, so this new class was called
ImageJob (and lives in
lib/, since it’s not really a model).
(This is of course not the first step, but I image that getting delayed_job installed and ready is not a problem.)
I tried to just enqueue the
Image itself, but that gave me some errors when de-serializing the object from the database. And we don’t really need to store the entire model in the database when we can just fetch it when we need it.
Then I added a column to the images-table, letting me know if it was still processing the image.
It defaults to
true, since Rails refused to set it to
true before Paperclip started doing its thing. Might have been solved with some more investigation, but this worked quickly. This means that for an existing site, you would have to create a job for each existing image, and let them be processed, or go change each existing image to be done.
Then it was time to change the
Image creation process, so we halted Paperclip if it was just created.
So in the model (
Image in this case), I hooked into Paperclip, and stopped it. Then added a job for it to be processed later.
Performing the resizing
Default images when processing
Since Paperclip doesn’t really know (or care) that we stopped it from creating images, it still returns the URLs for images that don’t exist. And we don’t want to serve non-existing images to visitors.
So instead of calling
@image.attachment.url(:thumbnail) in my views, I added a little helper method to the
Image-model with the same syntax, but returns the URL for a placeholder image if this image is still processing.
The default URL we use is stored as
@@default_url = "/system/:class/missing/:style.:locale.png", and gives URLs like
/system/images/missing/pending_thumbnail.en.png when we are waiting for the thumbnail.
Running the worker
This starts two job runners, and keeps them running. It’s important to restart them after each deploy, so in my
deploy.rb, right before I
touch tmp/restart.txt, I also have
sudo god restart ieye-beta-dj to take care of that. Might also be wise to have god start after a reboot, as I found out after researching why things weren’t being run.