rusty neuronnotes
A Simple Approach to Sidekiq Reschedule
This post is really old, tread carefully...
At my recent freelance project, I had a model called Campaign
and it had an end_date:datetime
attribute. When an instance created a sidekiq job will schedule to that date to set its status to inactive
. But, the owner can change that date along the way. So, I had to reschedule or create a new job each time :end_time
changed. I went with the latter. It just seemed a lot easier to work with. But then, the previous jobs shouldn’t run and I can’t directly check if the updated_at
and job's perform time
is the same because they might not be.
So, as a solution, I’ve added an attribute to Campaign
model to use as a job token.
# migration
class AddDeactivationJobTokenToCampaigns < ActiveRecord::Migration[5.2]
def change
add_column :campaigns, :deactivation_job_token, :bigint
end
end
Then in my model, I check before_update
if the campaign is active and end date is changed. If so, I call the :set_end_campaign_job
method. In that, I update the job token column with the current time.
# app/models/campaign.rb
before_update :set_end_campaign_job, if: Proc.new { |c| c.active? && c.end_date_changed? }
# ...
private
def set_end_campaign_job
self.update_column(:deactivation_job_token, Time.zone.now.to_i)
DeactivateCampaignJob.set(wait_until: self.end_date).perform_later(self, self.deactivation_job_token)
end
The last step is pretty simple. In the perform method, I check if the coming token is the same as the instance object’s token. That way, if the object is updated after the first job scheduled, the token won’t be the same and job just returns nil
.
# job
class DeactivateCampaignJob < ApplicationJob
queue_as :default
def perform(campaign, job_token)
if campaign.active? && (campaign.deactivation_job_token == job_token)
campaign.inactive!
end
end
end
© 2024 rusty neuron ― Textlog theme by Heiswayi Nrird