Skip to content

Instantly share code, notes, and snippets.

@IvanChepurnyi
Last active October 28, 2023 15:34
Show Gist options
  • Save IvanChepurnyi/aaa164a63d37c9dbbcbf8e7e75fa2fcd to your computer and use it in GitHub Desktop.
Save IvanChepurnyi/aaa164a63d37c9dbbcbf8e7e75fa2fcd to your computer and use it in GitHub Desktop.
Simple multi-process ReactPHP server with workers control
<?php
/**
* Copyright © EcomDev B.V. All rights reserved.
* See LICENSE.txt for license details.
*/
declare(strict_types=1);
$port = $argv[1];
$serverName = $argv[2];
$data = (object)[
'port' => $port,
'server' => $serverName,
'processed' => 0
];
require 'vendor/autoload.php';
$loop = React\EventLoop\Factory::create();
$server = new React\Http\Server(function (Psr\Http\Message\ServerRequestInterface $request) use ($data) {
$data->processed++;
return new React\Http\Response(
200,
['Content-Type' => 'text/plain'],
sprintf("Hello %s from server %s:%d!\n", $request->getServerParams()['REMOTE_ADDR'], $data->server, posix_getpid())
);
});
$socket = new React\Socket\Server('tcp://0.0.0.0:' . $port, $loop);
$server->listen($socket);
$fork = function (callable $child) {
$pid = pcntl_fork();
if ($pid === -1) {
throw new \RuntimeException('Cant fork a process');
} elseif ($pid > 0) {
return $pid;
} else {
posix_setsid();
$child();
exit(0);
}
};
$processes = [];
for ($i = 1; $i < 10; $i ++) {
$socket->pause();
$processes[] = $fork(function () use ($socket, $loop, $data) {
$socket->resume();
$loop->addSignal(SIGINT, function () use ($data, $loop) {
fwrite(STDERR, sprintf('%s finished running, Processed %d requests' . PHP_EOL, posix_getpid(), $data->processed));
$loop->stop();
});
$loop->run();
});
}
$loop->addSignal(SIGINT, function () use ($processes) {
foreach ($processes as $pid) {
posix_kill($pid, SIGINT);
$status = 0;
pcntl_waitpid($pid, $status);
}
$loop->stop();
});
$loop->run();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment