Удаление запущенных заданий из очереди Beanstalkd в laravel

Вот сценарий: я использую очередь Beanstalkd для отправки электронного письма в огромный список электронных писем (50000+), каждое электронное письмо должно иметь уникальный контент, поэтому запущенное задание перебирает все адреса, генерирует контент и отправляет почта.

Иногда пользователь может захотеть отменить операцию в середине отправки, например, во время выполнения задания и после того, как почта была отправлена, скажем, на 20000 адресов, пользователь нажимает «Стоп», что должно «удалить» задание.

что я сделал до сих пор, так это то, что мне удалось получить запущенный экземпляр задания, Queue::Push возвращает идентификатор задания, поэтому я сохраняю этот идентификатор, сохраненный в БД, и когда я хочу остановить задание, это то, что я пытался сделать

$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 имя очереди, я вижу, что задание все еще выполняется и выводит содержимое

Любая помощь ? Если есть лучший подход, чем пытаться получить задание и удалить его таким образом, я открыт для предложений, я подумал о сохранении идентификатора задания в базе данных (идентификатор, статус), и когда я хочу удалить его, я изменяю идентификатор статус, и в цикле, который выполняется внутри задания, он проверяет каждый раз, или, может быть, каждые 10 раз, и если статус равен, например, 1, то $job->delete(), но это будет так медленно, как это попадет в БД в каждом цикле.


person Sherif    schedule 03.08.2014    source источник
comment
Ваш последний вариант звучит правильно, но я бы использовал кеш вместо БД. И проверяйте каждую 100-ю итерацию или около того.   -  person Joseph Silber    schedule 03.08.2014


Ответы (1)


Итак, у вас есть основное задание, которое вы reserve() держите открытым, и в рамках этого задания вы напрямую создаете множество электронных писем.

Поскольку задание, которое вы пытаетесь удалить, в настоящее время зарезервировано, вы не можете его удалить. Даже если бы вы могли, как бы Beanstalkd проинформировал текущее задание?

Вместо этого я хотел бы, чтобы основной цикл проверял любые задания на какой-то отдельной контрольной трубке (вы могли бы выполнять быструю проверку, скажем, каждые 10 или 100 отправленных электронных писем) - просто запросить новое задание, но не ждать, если там ничего нет. . Если там есть задание, то основной процесс очищается и завершается.

Другая идея состоит в том, чтобы фактически не отправлять электронную почту в основном цикле, а вместо этого помещать в очередь детали того, какие электронные письма следует отправлять, по одному на адрес. Другие процессы читают эту массовую очередь и начинают отправлять электронные письма, но опять же, также считывают контрольную трубку (с сообщением с более высоким приоритетом, которое будет возвращено перед сообщением электронной почты / подробностей с более низким приоритетом). Если в контрольной трубке что-то есть, прекратите отправлять электронные письма. Вам потребуется как минимум столько сообщений STOP в контрольной трубке, сколько у вас есть рабочих.

person Alister Bulman    schedule 04.08.2014