/** * @throws Exception\RuntimeException * * @return Status\WorkerStatus */ public function query() { AdminEncoding::sendQueryMessage($this->channel, $this->adminCookie); foreach ($this->unreceivedMessages as $i => $message) { $status = AdminEncoding::getStatusMessage($message); if ($status !== null) { array_splice($this->unreceivedMessages, $i, 1); return $status; } } for (;;) { $message = $this->channel->receiveMessage(); $status = AdminEncoding::getStatusMessage($message); if ($status !== null) { return $status; } $this->unreceivedMessages[] = $message; } }
/** * @param SharedWorkerImplementationInterface $workerImpl * @param string $socketAddress * * @throws Exception\BindOrListenException * @throws Exception\RuntimeException */ public static function runSharedWorker(SharedWorkerImplementationInterface $workerImpl, $socketAddress) { $server = self::startListening($socketAddress); try { $loop = self::getLoop(); $loop->addReadStream($server, function () use($loop, $server, $workerImpl) { $socket = stream_socket_accept($server); $peerName = stream_socket_get_name($socket, true); $connection = Source::fromStream($socket, true, null, false); $channel = self::getChannelFactory()->createChannel(new BufferedSource($connection), $connection); Selectable::registerRead($loop, $channel, function () use($loop, $channel, $peerName, $workerImpl) { try { $message = $channel->receiveMessage(); } catch (IOException\UnderflowException $e) { Selectable::unregisterRead($loop, $channel); $workerImpl->onDisconnect($channel); return; } if (AdminEncoding::isStopMessage($message, self::$adminCookie, $privileged)) { if ($privileged) { $lock = Lock::acquire(); self::stopListening(); $workerImpl->onStop(); $lock->release(); } } elseif (AdminEncoding::isQueryMessage($message, self::$adminCookie, $privileged)) { $result = $workerImpl->onQuery($privileged); if (!$result instanceof WorkerStatus) { $result = new WorkerStatus($result); } AdminEncoding::sendStatusMessage($channel, $result); } else { $workerImpl->onMessage($message, $channel, $peerName); } }); $workerImpl->onConnect($channel, $peerName); }); $workerImpl->setLoop($loop); $workerImpl->initialize(); $loop->run(); $workerImpl->terminate(); } finally { self::stopListening(); } }