I am essentially writing the project in Railscast 383 - the second part, when the photo is uploaded directly to AWS S3, and the photo is then processed in the background by Sidekiq to create a thumbnail version of the photo. I'm on Rails 4.
My issue is that the Sidekiq job, after completing successfully, keeps repeating over and over, instead of just stopping.
Where am I going wrong? I can't see any difference between my code and that of the Railscast, other than I'm on Rails 4 (so strong parameters instead of attr_accessible
)
Photo class:
class Photo < ActiveRecord::Base
mount_uploader :image, ImageUploader
default_scope order('updated_at DESC')
after_save :enqueue_image
def image_name
File.basename(image.path || image.filename) if image
end
def enqueue_image
ImageWorker.perform_async(id, key) if key.present?
end
end
ImageWorker:
class ImageWorker
include Sidekiq::Worker
sidekiq_options retry: false
# sidekiq_options retry: 3
def perform(id, key)
photo = Photo.find(id)
photo.key = key
photo.remote_image_url = photo.image.direct_fog_url(with_path: true)
photo.save!
photo.update_column(:image_processed, true)
end
end
Uploader:
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWaveDirect::Uploader
include CarrierWave::RMagick
# storage :fog
#### storage defaults to fog when CarrierWaveDirect::Uploader is included ####
include CarrierWave::MimeTypes
process :set_content_type
version :thumb do
process :resize_to_limit => [200, 200]
end
version :medium do
process :resize_to_limit => [400, 400]
end
end
One reason for the sidekiq worker to be called again and again is because the perform_async
is called every time you save your photo object, which occurs within the sidekiq worker itself.
So every time the ImageWorker
is called, it saves the photo, calling the ImageWorker
again, creating the loop you are experiencing.
Are you sure you aren't missing a check for the :image_processed
tag to be true before calling the ImageWorker
again.
Try this:
def enqueue_image
ImageWorker.perform_async(id, key) if key.present? && !image_processed
end
This will check if the image was processed once before. I think this was probably meant to be set in the rails cast but the author forgot about it, otherwise the image_processed flag is obsolete.