/** * Send request to broker and get reply by hook or crook. * * Takes ownership of request message and destroys it when sent. * * * @param string $service The name of the service * @param Zmsg $request Request message * @return Zmsg Returns the reply message or NULL if there was no reply. */ public function send($service, Zmsg $request) { // Prefix request with protocol frames // Frame 0: empty (REQ emulation) // Frame 1: "MDPCxy" (six bytes, MDP/Client x.y) // Frame 2: Service name (printable string) $request->push($service); $request->push(Mdp::CLIENT); $request->push(""); if ($this->verbose) { $this->log('ZMQDEBUG', "send request to '%s' service:\n--\n%s", $service, (string) $request); } $request->setSocket($this->client)->send(); }
/** * Send request to broker and get reply by hook or crook. * * Takes ownership of request message and destroys it when sent. * * * @param string $service The name of the service * @param Zmsg $request Request message * @return Zmsg Returns the reply message or NULL if there was no reply. */ public function send($service, Zmsg $request) { // Prefix request with protocol frames // Frame 1: "MDPCxy" (six bytes, MDP/Client) // Frame 2: Service name (printable string) $request->push($service); $request->push(Mdp::CLIENT); if ($this->verbose) { $this->log("ZMQDEBUG", "send request to '%s' service:\n--\n%s", $service, (string) $request); } $retries_left = $this->retries; $read = $write = array(); while ($retries_left) { $request->setSocket($this->client)->send(); // Poll socket for a reply, with timeout $poll = new ZMQPoll(); $poll->add($this->client, ZMQ::POLL_IN); $events = $poll->poll($read, $write, $this->timeout); // If we got a reply, process it if ($events) { $request->recv(); if ($this->verbose) { $this->log("ZMQDEBUG", "received reply:\n--\n%s", $request); } if ($request->parts() < 3) { throw new MdpException(sprintf("Expected more than 2 parts, but %d received", $request->parts())); } $header = $request->pop(); if ($header !== Mdp::CLIENT) { throw new MdpException(sprintf("Unexpected header %s, %s is expected", $header, Mdp::CLIENT)); } $replyService = $request->pop(); if ($replyService != $service) { throw new MdpException(sprintf("Unexpected service %s, %s is expected.", $replyService, $service)); } //Success return $request; } elseif ($retries_left--) { if ($this->verbose) { $this->log("WARN", "no reply, reconnecting..."); } // Reconnect $this->connect(); // Resend message again $request->send(); } else { if ($this->verbose) { $this->log("ERROR", "permanent error, abandoning request"); break; } } } }
/** * Process message sent to us by a worker * * @param string $sender The address of the worker * @param \Scalr\System\Zmq\Zmsg $msg The message */ public function processWorker($sender, $msg) { $command = $msg->pop(); $workerReady = isset($this->workers[$sender]); $worker = $this->fetchWorker($sender); if ($command == Mdp::WORKER_READY) { if ($workerReady) { // Not first command in session $this->deleteWorker($worker, true); } elseif (strlen($sender) >= 4 && substr($sender, 0, 4) == 'mmi.') { // Reserved service name $this->deleteWorker($worker, true); } else { // Attach worker to service and mark as idle $serviceFrame = $msg->pop(); $worker->service = $this->fetchService($serviceFrame); $worker->service->workers++; $this->waitWorker($worker); } } elseif ($command == Mdp::WORKER_REPLY) { if ($workerReady) { // Remove & save client return envelope and insert the // protocol header and service name, then rewrap envelope. $client = $msg->unwrap(); $msg->push($worker->service->name); $msg->push(Mdp::CLIENT); $msg->wrap($client, ""); $msg->setSocket($this->socket)->send(); if ($this->verbose) { $this->log("ZMQDEBUG", "worker replied:\n--\n%s", (string) $msg); } $this->waitWorker($worker); } else { $this->deleteWorker($worker, true); } } elseif ($command == Mdp::WORKER_HEARTBEAT) { if ($workerReady) { $worker->expiry = microtime(true) + $this->heartbeatExpiry / 1000; } else { $this->deleteWorker($worker, true); } } elseif ($command == Mdp::WORKER_DISCONNECT) { $this->deleteWorker($worker, true); if ($this->verbose) { $this->log("ZMQDEBUG", "disconnect worker\n--\n%s", (string) $msg); } } else { if ($this->verbose) { $this->log("ERROR", "invalid input message\n--\n%s", (string) $msg); } } }