这是一个场景,我使用Beanstalkd队列向大量电子邮件列表(50000+)发送电子邮件,每封电子邮件必须有一些独特的内容,以便被解雇的作业遍历所有地址,生成内容并发送邮件。
有时用户可能想要在发送过程中取消操作,例如在作业运行时以及在发送邮件说20000个地址之后,用户点击"停止"应该"删除"这份工作。
到目前为止我所做的是我设法获取正在运行的作业实例,Queue :: Push返回作业ID,所以我将这个ID保存在DB中,当我想要停止工作时这就是我试图做
$phean= Queue::getPheanstalk();
$res = $phean->peek($Job_ID); // returns a Pheanstalk_Job
$job = new \Illuminate\Queue\Jobs\BeanstalkdJob(app() , $phean, $res , 'default') ;
$res = $job->delete() // returns NOT_FOUND ??
$data = $job->getRawBody() // returns correct data, so I'm sure this is the right job instance
所以为什么我会得到NOT_FOUND,尽管我使用的时候 supervisorctl tail -f queuename 我可以看到作业仍在运行并输出内容
有任何帮助吗?如果有一个更好的方法,而不是尝试获取工作并以这种方式删除它,我可以接受建议,我考虑将作业ID保存在数据库中(ID,状态),当我想删除它时,我改变ID状态,并且在作业中运行的循环中,它每次检查,或者每10次检查一次,如果状态等于1,例如$ job-> delete(),那么这将是如此慢,因为它会在每个循环中击中db。
答案 0 :(得分:2)
所以你有一份主要工作,你reserve()
并保持开放,在那份工作中,你可以直接创建许多电子邮件。
由于您要删除的作业目前已保留,因此您无法将其删除。即使你可以,Beanstalkd会如何通知当前正在运行的工作?
相反,我会对某个单独的控制管上的任何作业进行主循环检查(您可以快速检查每个发送的10或100封电子邮件) - 只是为了申请一份新工作,但不等待,如果没有&# 39;那里有什么。如果那里有工作,那么主要流程会清理并退出。
另一个想法是不在主循环中实际发送电子邮件,而是将每个地址发送的电子邮件的详细信息放入队列中。其他进程读取大量队列并开始发送电子邮件,但同样,还读取了一个控制管(具有更高优先级的消息,将在优先级较低的电子邮件/详细消息之前返回)。如果控制管中有任何内容,请停止发送电子邮件。控制管中至少需要与工作人员一样多的STOP消息。