优雅地停止发电机

时间:2018-03-18 15:00:36

标签: amphp

请考虑以下代码:

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 个答案:

答案 0 :(得分:0)

没有这样的选择,但您可以通过添加标记轻松地在简单的应用程序中实现您想要的功能。

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);
    }
});

这将继续当前请求并在之后退出。