Изящно останавливая генераторы
Рассмотрим следующий код:
Loop::run(function() {
Loop::onSignal(SIGINT, function () use ($w) {
echo "Caught SIGINT! exiting ...\n";
Loop::stop();
});
while([$jobId, $jobData] = yield $beanstalk->reserve()) {
$response = yield $httpClient->send($request);
yield $beanstalk->delete($jobId);
}
});
Насколько я понимаю, когда этот код получает SIGINT
Обратный звонок в Loop::onSignal
будет выполнен на следующем тике, и, таким образом, цикл остановится и программа завершится.
В этом случае, если $httpClient->send()
в while
цикл еще не завершен, следующая строка не будет выполнена, а сообщение Beanstalk не будет удалено. Затем задание Beanstalk будет повторено, и это может вызвать проблему, если HTTP-запрос не идемпотентен. Мы можем заменить HTTP-запрос вызовом из базы данных.
Есть ли способ сказать циклу, чтобы он не выполнял новые генераторы и ждал завершения работы генераторов, когда SIGINT
получил?
Я пытался обернуть голову вокруг этого, но не смог найти решение.
1 ответ
Такой опции нет, но вы можете легко достичь желаемого в простом приложении, добавив флаг.
Loop::run(function() {
$running = true;
Loop::onSignal(SIGINT, function () use (&$running) {
echo "Caught SIGINT! exiting ...\n";
$running = false;
});
while($running && [$jobId, $jobData] = yield $beanstalk->reserve()) {
$response = yield $httpClient->send($request);
yield $beanstalk->delete($jobId);
}
});
Это просто продолжит текущий запрос и завершит работу позже.