Sidekiq stop one single, running job
Asked Answered
H

3

25

So I need to stop a running Job in Sidekiq (3.1.2) programmatically, not a scheduled one. I did read the API documentation but didn't really find anything about cancelling running jobs. Is this possible with sidekiq?

When this is not directly possible, my idea was to circumvent this, by raising an exception in the job when I call the signal, then deleting the job from the retryset. This is clearly not optimal though.

Thanks in advance

Hamblin answered 17/9, 2014 at 11:45 Comment(2)
How did you resolve this problem then? Could you share your workaround?Herman
Look at the FAQ from the first answer, it explains the idea really well. I did something similar by adding multiple breakpoints to the perform action, (i.e. at the beginning of an each block). Thats pretty much dependent on your use case, where/when you want to stop execution of your perform methodHamblin
T
14

Correct, the only way to stop a job is for the job to stop itself. Your application must implement that logic.

https://github.com/mperham/sidekiq/wiki/FAQ#how-do-i-cancel-a-sidekiq-job

Tejada answered 17/9, 2014 at 20:6 Comment(5)
Could you please elaborate on it a little more? I don't know how to stop a job by itselfHerman
Wow, I actually implented something similar to this version by using Redis and storing all jids in a hash, then adding breakpoints in my perform method, each time checking whether the current jid was set in redisHamblin
Any opposition to killing the thread, as suggested in another answer, when it is desired to interrupt the job?Gherardi
If that method was safe, don't you think Sidekiq would allow it?Tejada
looking at the above link, I reckon that once we call the setex function, the job's status is set to cancelled and it stops executing. Now, when this job attempts to run again, then, the return if cancelled? part effectively completes/ends the job. Is that a correct interpretation? @MikePerhamPylon
F
7

If you know the long running job's Thread ID, its possible to terminate it from another task:

class ThreadLightly
  include Sidekiq::Worker

  def perform(tid)
    puts "I'm %s, and I'll be terminating TID: %s..." % [self.class, tid]
    Thread.list.each {|t|
      if t.object_id.to_s == tid
        puts "Goodbye %s!" % t
        t.exit
      end
    }
  end
end

You can trigger it from the sidekiq_pusher:

bundle exec ./pusher.rb ThreadLightly $YOURJOBSTHREADID

You'll need to log the Thread.current.object_id from each job since the UI dosn't show it. Also, if you run distributed sidekiqs, you'll need to run this task until it runs on the same instance.

Functionalism answered 28/4, 2015 at 16:40 Comment(2)
Exactly what I'm looking for!. One little correction: at this moment (2017) you should use object_id.to_s(36).Trapani
Im not sure this would work if you have sidekiq running over multiple instances. What would happen if the job you want to kill is on instance A but this worker executes on instance B? As far as I know you have no way of knowing to which process this worker will be assignedMoazami
N
7

Using Sidekiq Dashboard.

Another way to stop running job is, Stop the Sidekiq process.

enter image description here

and It will take some time to stop sidekiq process. If the Sidekiq process stop, all job were running, will be located back to enqued section. so if you re-start sidekiq process, it will running again.

You need to delete all jobs in enqued section. You can do it using dashboard. or running this kind of command on rails console.

## queue_name = 'logger'
## Sidekiq::Queue.new(queue_name).each { |e| e.delete }

# e.g.
Sidekiq::Queue.new('logger').each { |e| e.delete }

Or... using dashboard...

enter image description here

enter image description here

It will be removed from the all job queue. Now you can re-start your sidekiq process.

Noxious answered 2/6, 2023 at 10:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.