/** * @codeCoverageIgnore */ protected function processWork() : \Generator { $transmitter = new SocketTransmitter(new SocketStream($this->socket)); while (true) { list($type, $payload) = (yield from $transmitter->receive()); if ($type === SocketTransmitter::TYPE_EXIT) { yield from $transmitter->send($payload, $type); break; } try { if (isset($payload['func'])) { if (\substr($payload['func'], 0, 1) === '@') { $result = \substr($payload['func'], 1)(...$payload['args'] ?? []); } else { $result = $payload['func'](...$payload['args'] ?? []); } } elseif (isset($payload['class']) && isset($payload['method'])) { $result = $payload['class']::{$payload['method']}(...$payload['args'] ?? []); } else { throw new \RuntimeException('No callable target passed to threaded worker'); } } catch (\Throwable $e) { yield from $transmitter->sendError($e); continue; } yield from $transmitter->send($result, SocketTransmitter::TYPE_DATA); } }
public function executeStaticMethod(string $class, string $method, array $args = []) : Awaitable { return new Task($this->executor->execute(function () use($class, $method, $args) { yield from $this->transmitter->send(['class' => $class, 'method' => $method, 'args' => $args], SocketTransmitter::TYPE_DATA); list($type, $payload) = (yield from $this->transmitter->receive()); if ($type === SocketTransmitter::TYPE_DATA) { return $payload; } })); }
public static function connect(string $url, $workerId) : IpcClient { $errno = null; $errstr = null; $socket = @\stream_socket_client($url, $errno, $errstr, 5); if ($socket === false) { throw new \RuntimeException(\sprintf('Failed to connecto to IPC server "%s": [%s] %s', $url, $errno, $errstr)); } \stream_set_read_buffer($socket, 0); \stream_set_write_buffer($socket, 0); $socket = new SocketStream($socket); $transmitter = new SocketTransmitter($socket); // Perform a blocking handshake. $transmitter->sendSync($workerId, SocketTransmitter::TYPE_HANDSHAKE); return new IpcClient($workerId, $socket, $transmitter); }
protected function handleHandshake(SocketStream $socket) : \Generator { $transmitter = new SocketTransmitter($socket); list($type, $message) = (yield from $transmitter->receive()); if ($type !== SocketTransmitter::TYPE_HANDSHAKE) { throw new \RuntimeException('Failed to perform worker handshake'); } $id = (int) $message; $this->workers[$id]->start($socket, $transmitter); }
private static function handshake(SocketStream $socket) : \Generator { $transmitter = new SocketTransmitter($socket); list($type, $data) = (yield from $transmitter->receive()); if ($type !== SocketTransmitter::TYPE_HANDSHAKE || !isset($data['id'])) { return $socket->close(); } $id = $data['id']; if (empty(self::$handshakes[$id])) { return $socket->close(); } list($worker, $defer) = self::$handshakes[$id]; unset(self::$handshakes[$id]); if (empty(self::$handshakes) && self::$serverAwait !== null) { self::$serverAwait->cancel(new PoolShutdownException('Handshakes done')); } $worker->connect($socket, $transmitter); self::$sharedWorkers[$id] = $worker; $defer->resolve($worker); }
\error_reporting(-1); \ini_set('display_errors', false); \set_error_handler(function ($severity, $message) { if ($severity & \error_reporting()) { throw new \Error($message, $severity); } }); require_once $_SERVER['autoloader']; $exitCode = 1; Loop::execute(function () use(&$exitCode) { new Coroutine(function () use(&$exitCode) { $id = (string) $_SERVER['id']; list($protocol, $peer) = \explode('://', (string) $_SERVER['ipc'], 2); $factory = new SocketFactory($peer, $protocol); $socket = (yield $factory->createSocketStream(2)); $transmitter = new SocketTransmitter($socket); try { yield from $transmitter->send(['id' => $id], SocketTransmitter::TYPE_HANDSHAKE); while (true) { list($type, $payload) = (yield from $transmitter->receive()); if ($type === SocketTransmitter::TYPE_EXIT) { yield from $transmitter->send($payload, $type); $socket->close(); $exitCode = 0; break; } try { if (isset($payload['func'])) { if (\substr($payload['func'], 0, 1) === '@') { $result = \substr($payload['func'], 1)(...$payload['args'] ?? []); } else {