每当我使用capistrano部署或运行cap production delayed_job:restart
时,我最终都会将当前正在运行的delayed_job行保持锁定状态。
delayed_job进程已成功停止,新的delayed_job进程已启动,新进程将锁定新行。问题是最后一个进程'仍然在那里&标记为已锁定。所以我必须手动进入数据库,删除该行,然后手动将该作业添加回队列,以便新的delayed_job进程进入。
有没有办法清理数据库&重新排队上一个作业会自动发生吗?
答案 0 :(得分:2)
我有同样的问题。只要工作被强行杀死,就会发生这种情况。部分问题是工作进程由守护进程gem而不是delayed_job本身管理。我正在研究解决这个问题的方法,例如:
如果我想出一个解决方案,我会在这里回复。
答案 1 :(得分:0)
SIGINT
上引发异常。@John Carney 是对的。简而言之,所有 delayed_job
工人在重新部署时都会收到类似 SIGINT
(不错的中断)的消息。默认情况下,delayed_job
工作人员将完成他们当前的工作(如果他们正在处理一项工作),然后正常终止。
但是,如果他们正在处理的作业是一个运行时间较长的作业,那么守护程序管理器会等待一段时间,然后才会感到恼火并发送更严重的中断信号,例如 SIGTERM
或 { {1}}。此等待时间以及发送的内容实际上取决于您的设置和配置。
当这种情况发生时,SIGKILL
工作器会立即被杀死,而无法完成其正在处理的工作,甚至无法自行清理并将工作标记为不再锁定。
这最终会导致一个标记为“锁定”但锁定到不再存在的进程/工人的“搁浅”作业。不好。
这就是问题的症结所在以及正在发生的事情。要解决这个问题,您有两个主要选择,具体取决于您的工作内容(我们两者都使用):
您可以通过将 delayed_job
配置设置为 raise_signal_exceptions
或 :term
来实现:
true
此配置选项接受 Delayed::Worker.raise_signal_exceptions = :term
、:term
或 true
(默认)。您可以阅读有关原始提交 here 的更多信息。
我会先尝试使用 false
,看看是否能解决您的问题。如果没有,您可能需要将其设置为 :term
。
设置为 true
或 :term
将优雅地引发异常并解锁作业,以便另一个 true
工人接手并开始处理它。
将其设置为 delayed_job
意味着您的 true
工人甚至不会尝试完成他们正在从事的当前工作。他们会立即引发异常,解锁工作并自行终止。
这实际上取决于您的重新部署等。在我们的例子中,我们使用 Cloud66 来处理部署,所以我们只需要使用它们进行配置。但这就是我们的样子:
delayed_job
在重新部署时,这会告诉守护程序管理器按照以下步骤将每个 stop_sequence: int, 172800, term, 90, kill # Allows long-running delayed jobs to finish before being killed (i.e. on redeploy). Sends SIGINT, waits 48 hours, sends SIGTERM, waits 90 seconds, sends SIGKILL.
工人:
delayed_job
。SIGINT
,如果工人还活着。SIGTERM
,如果工人还活着。无论如何,这应该有助于让您走上正确的轨道,为自己正确配置。
我们通过设置长时间超时以及在收到 SIGKILL
时引发异常来使用这两种方法。这确保了如果有一个作业超过了 2 天的限制,它至少会引发异常并解锁该作业,让我们能够进行调查,而不是仅仅留下一个被锁定到不再存在的进程的搁浅作业。