Sidekiq-ORM Project
A fairly common Sidekiq::Worker
pattern, is a worker which does the following:
* Receives a model.id as it's argument.
* Loads the specified model.
* Verifies that the model exists.
* Performs some additional validation.
(since the model may have changed since the worker was enqueued)
* If all is well, runs some application logic on the mode.
lets checkout an example:
class UserTaskWorker
include Sidekiq::Worker
def perform(user_id)
user = User.find(user_id)
return unless user.present?
return unless user.active?
UserService.run(user)
end
end
Sidekiq::ActiveRecord::TaskWorker
wraps this boilerplate and lets you access the model, using the perform_on_model
method:
class UserTaskWorker < Sidekiq::ActiveRecord::TaskWorker
sidekiq_task_model :user # or User
def perform_on_model
current_user = task_model
UserService.run(current_user)
end
end
The sidekiq_task_model
is the task's model. it can be either a symbol (:user
) or the model class (User
).
Note that perform_on_model
will only be called if the model exist and valid. (more on that soon)
In case the task was called with additional arguments, will be passed to perform_on_model
e.g:
UserTaskWorker.perform_async(user.id, {:new_email => true})
def perform_on_model(options)
UserService.run(task_model, options[:new_email])
end
For better readability, you can use an alias of task_model
which is the same as name class name:
sidekiq_task_model :user
def perform_on_model(service_options)
UserService.run(user, service_options)
end
Checkout the full example.
Additionally, you can define the following methods which serve as hooks for each use-case:
Add this method hook, which will be invoked in the event the model wasn't found.
def not_found_model(user_id)
Rails.logger.error "User not found for ID:#{user_id}"
end
Add this method hook, which will be invoked before the perform_on_model
is called.
If the check fails, perform_on_model
will not be called.
When the method isn't defined, it returns true
by default.
def should_perform_on_model?
task_model.active?
end
Add this method hook, which will be invoked in the event the model didn't pass the validation.
def did_not_perform_on_model
Rails.logger.error "User #{task_model.id} is invalid"
end
The hooks order of execution is:
* not_found_model
* should_perform_on_model?
* perform_on_model || did_not_perform_on_model
To change the default task options, you can use the sidekiq_task_options
to specify the following:
In some cases the model identifier is not :id
.
To handle this, you can define the :identifier_key
option:
sidekiq_task_options :identifier_key => :token
Which will load fetch the User by the :token
attribute.