Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resque jobs, how to stop running job

My Resque worker class

class WebWorker

  @queue = :jobs_queue

  def self.perform(id)
  //bunch of code here
  end
end

I remove from the queue a certain job like this

Resque.dequeue(WebWorker,id)

But I would like to stop running job and restart, how would I do this?

like image 982
Aydar Omurbekov Avatar asked Nov 20 '13 13:11

Aydar Omurbekov


People also ask

How does Resque work?

Resque is our Redis-backed library for creating background jobs, placing those jobs on multiple queues, and processing them later. Background jobs can be any Ruby class or module that responds… those jobs on multiple queues, and processing them later. can do both.

How Resque works in rails?

If you are using Resque-scheduler then it will add more options for you in the resque-web UI. Those options allows you to view queues and manually start queuing. Other option is for viewing pending jobs in the delayed queues. Again, restart server, and refresh the browser page.


2 Answers

Try the unregister_worker as follow:

Resque.workers.each(&:unregister_worker)

This command will stop the work and set it as failed.

http://www.rubydoc.info/gems/resque/Resque/Worker:unregister_worker

like image 192
joaofraga Avatar answered Oct 04 '22 01:10

joaofraga


If you feel like killing/stopping an ongoing job without marking it as a failed job, you can use this hack.

class Task

    @queue = :queue_name

    def self.perform(parameters)

        pid = Process.fork do
            Task.work parameters
        end

        #puts "parent, pid #{Process.pid}, waiting on child pid #{pid}"
        Process.wait
    end

    def self.work(parameters)
        #Your perform code here
    end
end

Now, where you want your stop this code, just reach to the resque worker currently doing the job which you want to stop. and kill its child's child process. Something like killing grandchild process of Worker.

Explanation:

A worker forks a child process in which perform function run its code. If we directly kill this child process, then this job will stop but it will be marked as failed job. That's why we have forked another child process in self.perform and now killing perform's child process will stop this running job and also, it will not be marked as failed. Now we can again enqueue the job. So, the task is to how to reach to the worker doing the job that we need to stop (._.")

I have managed to do this by writing this code for a UNIX based system:

Resque.workers.each do |worker|
    #If condition : "current worker is working and is working on the job that we want to stop and is operating on the queue that we require " and please change this condition as per your requirement          
    if worker.working? and worker.queues.include?("queue_name") and worker.job["payload"]["args"].first==post_id
            victim = %x[pgrep -P #{worker.pid}] #Getting child's PID
            victim.strip!
            victim = %x[pgrep -P #{victim}] #Getting grandchild's PID of worker
            victim.strip!
            %x[kill -9 #{victim.to_i}]
    end
end
like image 45
Aakash Gupta Avatar answered Oct 04 '22 00:10

Aakash Gupta