Изящно закрыть приложение ReactPhp

Вопрос очень связан с Получите только N сообщений от RabbitMQ с реакцией \ stomp, проверьте их отдельно и выйдите, но немного более общий.

Например, у меня медленная операция ввода-вывода:

$port = 4000;

$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server($loop);
$socket->on('connection', function ($conn) use ($loop){

$conn->on('data', function ($data) use ($conn, $loop) {

if ($data == 42) {
// this instantly stop the loop
$loop->stop();
}

$process = new React\ChildProcess\Process('sleep 5; echo ' . $data);

$loop->addTimer(0.001, function($timer) use ($process, $conn) {
$process->start($timer->getLoop());

$process->stdout->on('data', function($output) use ($conn) {
if ($output) {
$conn->write("> $output");
}
});
});
});
});
echo "Socket server listening on port $port.\n";
echo "You can connect to it by running: telnet localhost $port\n";
$socket->listen($port);
$loop->run();
echo "exited";

когда я бегу $loop->run(); Я хочу остановить это в какой-то момент, например по таймеру, после принятия N запросов или любого другого события, например pcntl_signalили утверждение данных, как в примере.

Задача состоит в том, чтобы завершить все начатые работы до выхода, и я не могу понять, как этого добиться.

В консоли сервера у меня есть:

Socket server listening on port 4000.
You can connect to it by running: telnet localhost 4000
exited

В клиентской консоли у меня есть:

Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
1
2
3
4
5
> 1
> 2
42
Connection closed by foreign host.

где 1,2,3,4,5 были введены с интервалом в 1 секунду

Вместо этого я хотел бы видеть что-то вроде этого:

Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
1
2
3
4
5
> 1
> 2
42
> 3
6
> 4
> 5
Connection closed by foreign host.

6

Решение

Как упоминалось в комментариях, для корректного выхода необходимо отслеживать запущенные процессы и останавливать цикл только после завершения всех процессов:

$socket->on('connection', function ($conn) use ($loop) {
$processes = new SplObjectStorage();
$stop = false;

$conn->on('data', function ($data) use ($conn, $loop, $processes, &$stop) {
if ('42' === trim($data)) {
$stop = true;
if (!$processes->count()) {
$loop->stop();
}
}

if ($stop) {
return;
}

$process = new React\ChildProcess\Process('sleep 5; echo ' . $data);
$processes->attach($process);

$process->on('exit', function () use ($process, $processes, &$stop, $loop) {
$processes->detach($process);

if ($stop && !$processes->count()) {
$loop->stop();
}
});

$loop->addTimer(0.001, function($timer) use ($process, $conn) {
$process->start($timer->getLoop());

$process->stdout->on('data', function($output) use ($conn) {
if ($output && '42' !== trim($output)) {
$conn->write("> $output");
}
});
});
});
});
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]