如何在Rails上查找并终止正在运行的Resque作业?

时间:2012-09-04 16:51:36

标签: ruby-on-rails ruby queue resque jobs

我正在使用Resque处理Rails应用程序上的一些后台作业。

问题是客户可以取消这些工作,所以:

  • 如果作业仍在队列中:将其取消

    Resque.dequeue(GitHub::Jobs::UpdateNetworkGraph, 'repo:135325')
    
  • 如果作业已完成:什么都不做

  • 如果作业正在运行:???

有没有办法以编程方式找到作业,如果它正在运行,请告诉它立即停止?我主要担心的是确保我杀死了所需的工作,而不是当前正在处理的工作,因为它可能是一个不同的工作,直到我问它是否正在运行,直到我杀死它。

2 个答案:

答案 0 :(得分:2)

我不认为resque存储fork进程的process id,它确实存在 log虽然但它不存储child process forked

的进程ID

您可以在第139行

中看到here

关于如何提取正在运行的resque作业的进程ID的问题,我认为使用redis数据结构在你的工作中自己做的方法

因此,请考虑以下代码是您使用redis哈希(running_process)创建作业的执行操作,并使用当前时间戳添加当前process_id

class MyJob
 @queue = :myjob

 def self.perform
   field = Time.now.to_i
   redis.hsetnx "running_process",field,Process.pid 
   ### Rest of the code



   #### when the code is about to finish 
   ##remove the finish process from the 
   redis.hdel "running_process",field
  end

现在你可以通过简单地查询redis“running_process”hash来得到所有正在运行的进程的列表

redis.hgetall "running_process"

此处的警告如果resque作业失败,则进程ID将永远不会被清除

哈希你做的只是确保你交叉检查你收集的process id

来自redis哈希的

实际上是running resque job

希望这个帮助

答案 1 :(得分:0)

如果你想杀死/停止正在进行的工作而不将其标记为失败的工作,你可以使用这个黑客。

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

现在,您希望停止此代码,只需访问当前正在执行您要停止的作业的resque工作人员。并杀死孩子的孩子过程。就像杀死工人的孙子过程一样。

<强>解释

一个worker分叉子进程,其中perform函数运行其代码。如果我们直接杀死此子进程,则此作业将停止,但它将被标记为失败的作业。这就是为什么我们在self.perform中分叉了另一个子进程,现在kill执行的子进程将停止这个正在运行的作业,并且它也不会被标记为失败。现在我们可以再次排队。所以,任务是如何联系到我们需要停止工作的工人(._。“)

我已经设法通过为基于UNIX的系统编写此代码来实现此目的:

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