Exemple #1
0
 /**
  * @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);
     }
 }
Exemple #2
0
 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;
         }
     }));
 }
Exemple #3
0
 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);
 }
Exemple #4
0
 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);
 }
Exemple #5
0
 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);
 }
Exemple #6
0
\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 {