calyxofheld
calyxofheld

Reputation: 2178

cancelling a sheduled Sidekiq job in Rails

Some Sidekiq jobs in my app are scheduled to change the state of a resource to cancelled unless a user responds within a certain timeframe. There is a lot of information about how to best accomplish this task, but none of it actually cancels the job.

To cancel a job, the code in the wiki says:

class MyWorker
 include Sidekiq::Worker

 def perform(thing_id)
  return if cancelled?
  thing = Thing.find thing_id
  thing.renege!
 end

 def cancelled?
  Sidekiq.redis {|c| c.exists("cancelled-#{jid}") }
 end

 def self.cancel!(jid)
  Sidekiq.redis {|c| c.setex("cancelled-#{jid}", 86400, 1) }
 end
end

Yet here it's suggested that I do something like

 def perform(thing_id)
  thing = Thing.find thing_id
  while !cancel?(thing)
   thing.ignore!
  end
 end

 def cancel?(thing_id)
  thing = Thing.find thing_id
  thing.matched? || thing.passed?
 end

What's confusing about this and similar code on the wiki is none of it actually cancels the job. The above example just performs an update on thing if cancelled? returns false (as it should), but doesn't cancel if and when it returns true in the future. It just fails with an aasm transition error message and gets sent to the RetrySet. Calling MyWorker.cancel! jid in model code throws an undefined variable error. How can I access that jid in the model? How can actually cancel or delete that specific job? Thanks!

Upvotes: 6

Views: 2608

Answers (3)

calyxofheld
calyxofheld

Reputation: 2178

Ok, so turns out I had one question already answered. One of the code sets I included was a functionally similar version of the code from the wiki. The solution to the other question ("how can I access that jid in the model?") seems really obvious if you're not still new to programming, but basically: store the jid in a database column and then retrieve/update it whenever it's needed! Duh!

Upvotes: 0

Rubin bhandari
Rubin bhandari

Reputation: 1951

You can do this but it won't be efficient. It's a linear scan for find a scheduled job by JID.

require 'sidekiq/api' Sidekiq::ScheduledSet.new.find_job(jid).try(:delete) Alternatively your job can look to see if it's still relevant when it runs.

Upvotes: 1

Mike Perham
Mike Perham

Reputation: 22228

# The wiki code
class MyWorker
 include Sidekiq::Worker

 def perform(thing_id)
  return if cancelled?

  # do actual work
 end

 def cancelled?
  Sidekiq.redis {|c| c.exists("cancelled-#{jid}") }
 end

 def self.cancel!(jid)
  Sidekiq.redis {|c| c.setex("cancelled-#{jid}", 86400, 1) }
 end
end

# create job
jid = MyWorker.perform_async("foo")

# cancel job
MyWorker.cancel!(jid)

Upvotes: 8

Related Questions