我有以下代码:
[23, 45, 69, 20].each do |page_id|
Resque.enqueue(ProcessPage, page_id)
end
我想知道所有这些工作何时完成处理以通过电子邮件通知用户。我的第一次尝试是在工作的最后通知用户,但这对每项工作都是单独的。
我找到了这个宝石resque-status,基本上你可以这样做:
job_ids = []
[23, 45, 69, 20].each do |page_id|
job_ids << ProcessPage.create(page_id)
end
然后您可以通过执行以下操作来检查作业的状态:
status = Resque::Plugins::Status::Hash.get(job_id)
让我感到困惑的是......我什么时候应该检查所有状态?我的意思是,我会在一段时间内检查所有工作的状态吗?这会让服务器超时,任何想法我怎么能这样做?
答案 0 :(得分:3)
我不会在这里粘贴任何代码,因为看起来你对如何写作业非常熟悉,但想想以下想法:
你应该有一个resque作业,它可以获取和处理的数组。 此resque作业为每个ID创建单个resque作业,以便并行处理它们。 在为特定ID创建resque作业之后,它将创建另一个resque作业,它获取id列表并定期检查它们以查看它们是否已完成。完成后,此作业将向用户发送电子邮件。
通过这种模式,你可以享受所有的世界:
更新:
支票转发作业的伪代码:
class CheckerJob
@queue = :long
def self.perform(ids)
finished = []
while finished.size < ids.size
ids.each do |id|
finished << id if job_finished?(id)
end
sleep 10
end
send_email_to_user
end
end
现在您要做的就是实施job_finished?(id)
和send_email_to_user
方法。
答案 1 :(得分:0)
简单的解决方案是让你的工作列出一些ID:
Class Job
def self.perform(ids)
threads = ids.inject([]) do |memo, id|
memo << Thread.new { # whatever }
end
ThreadsWait.join_all(*threads)
# All threads are done
# Notify user that job is finished
end
end
没有工作来检查这个是否已经完成。如果您打算采用这种方式,请订阅Redis事件http://redis.io/topics/internals-rediseventlib
更新:添加了多线程
答案 2 :(得分:0)
这样做怎么样?
Resque.enqueue_to("page_processes#{user.id}", ProcessPage, page_id)
#code in ProcessPageWorker below
def self.perform(page_id, user_id)
#work
# code below notifies user if the 'page_processes' queue is equal to 1
notify_user if Resque.size("page_processes#{user_id}") == 1
end
我们将作业排入名为“page_processes”的队列中,加上用户的ID。完成每项工作后,我们会检查“page_processes#{user_id}”队列的大小。如果队列等于1,则意味着正在处理的作业是队列中的最后一个作业,因此我们应该通知用户。我们在队列名称中包含user_id以确保队列的唯一名称。
如果有帮助,请告诉我。