我正在使用Resque处理Rails应用程序上的一些后台作业。
问题是客户可以取消这些工作,所以:
如果作业仍在队列中:将其取消
Resque.dequeue(GitHub::Jobs::UpdateNetworkGraph, 'repo:135325')
如果作业已完成:什么都不做
如果作业正在运行:???
有没有办法以编程方式找到作业,如果它正在运行,请告诉它立即停止?我主要担心的是确保我杀死了所需的工作,而不是当前正在处理的工作,因为它可能是一个不同的工作,直到我问它是否正在运行,直到我杀死它。
答案 0 :(得分:2)
我不认为resque存储fork进程的process id
,它确实存在
log
虽然但它不存储child process forked
您可以在第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
实际上是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