Beispiel #1
0
 public function testComplex()
 {
     $context = new \ZMQContext();
     $output = new \ZMQSocket($context, \ZMQ::SOCKET_DEALER);
     $output->bind("inproc://zmsg_selftest");
     $input = new \ZMQSocket($context, \ZMQ::SOCKET_ROUTER);
     $input->connect("inproc://zmsg_selftest");
     //  Test send and receive of single-part message
     $zmsgo = new Zmsg($output);
     $zmsgo->setLast("Hello");
     $this->assertTrue($zmsgo->getLast() == "Hello");
     $zmsgo->send();
     $zmsgi = new Zmsg($input);
     $zmsgi->recv();
     $this->assertTrue($zmsgi->parts() == 2);
     $this->assertTrue($zmsgi->getLast() == "Hello");
     //  Test send and receive of multi-part message
     $zmsgo = new Zmsg($output);
     $zmsgo->setLast("Hello");
     $zmsgo->wrap("address1", "");
     $zmsgo->wrap("address2");
     $this->assertTrue($zmsgo->parts() == 4);
     $zmsgo->send();
     $zmsgi = new Zmsg($input);
     $zmsgi->recv();
     $this->assertTrue($zmsgi->parts() == 5);
     $zmsgi->unwrap();
     $this->assertTrue($zmsgi->unwrap() == "address2");
     $zmsgi->setLast(sprintf("%s%s", 'W', "orld"));
     $this->assertTrue($zmsgi->getLast() == "World");
     //  Pull off address 1, check that empty part was dropped
     $zmsgi->unwrap();
     $this->assertTrue($zmsgi->parts() == 1);
     //  Check that message body was correctly modified
     $part = $zmsgi->pop();
     $this->assertTrue($part == "World");
     $this->assertTrue($zmsgi->parts() == 0);
     // Test load and save
     $zmsg = new Zmsg();
     $zmsg->setLast("Hello");
     $zmsg->wrap("address1", "");
     $zmsg->wrap("address2");
     $this->assertTrue($zmsg->parts() == 4);
     $fh = fopen(sys_get_temp_dir() . "/zmsgtest.zmsg", 'w');
     $zmsg->save($fh);
     fclose($fh);
     $fh = fopen(sys_get_temp_dir() . "/zmsgtest.zmsg", 'r');
     $zmsg2 = new Zmsg();
     $zmsg2->load($fh);
     assert($zmsg2->getLast() == $zmsg->getLast());
     fclose($fh);
     $this->assertTrue($zmsg2->parts() == 4);
 }
Beispiel #2
0
 /**
  * Send reply, if any, to broker and wait for next request.
  *
  * @param   Zmsg $reply  optional  Reply message object
  * @return  Zmsg Returns if there is a request to process
  */
 public function recv($reply = null)
 {
     // Format and send the reply if we were provided one
     if (!$reply && $this->expectReply) {
         throw new MdpException("Reply message is expected");
     }
     if ($reply) {
         $reply->wrap($this->replyTo);
         $this->send(Mdp::WORKER_REPLY, null, $reply);
     }
     $this->expectReply = true;
     $read = $write = [];
     while (true) {
         $poll = new ZMQPoll();
         $poll->add($this->worker, ZMQ::POLL_IN);
         $events = $poll->poll($read, $write, $this->heartbeat);
         if ($events) {
             $zmsg = new Zmsg($this->worker);
             $zmsg->recv();
             if ($this->verbose) {
                 $this->log("ZMQDEBUG", "received message from broker:\n--\n%s", (string) $zmsg);
             }
             $this->liveness = self::HEARTBEAT_LIVENESS;
             if ($zmsg->parts() < 3) {
                 throw new MdpException(sprintf("Expected more then 2 parts, but %d received", $zmsg->parts()));
             }
             $zmsg->pop();
             $header = $zmsg->pop();
             if ($header !== Mdp::WORKER) {
                 throw new MdpException(sprintf("Expected %s header, %s has been actually received", Mdp::WORKER, $header));
             }
             $command = $zmsg->pop();
             if ($command == Mdp::WORKER_REQUEST) {
                 // We should pop and save as many addresses as there are
                 // up to a null part, but for now, just save one…
                 $this->replyTo = $zmsg->unwrap();
                 // We have a request to process
                 return $zmsg;
             } elseif ($command == Mdp::WORKER_HEARTBEAT) {
                 // Do nothing for heartbeats
             } elseif ($command == Mdp::WORKER_DISCONNECT) {
                 $this->connect();
             } else {
                 if ($this->verbose) {
                     $this->log("ERROR", "invalid input message\n--\n%s", (string) $zmsg);
                 }
             }
         } elseif (--$this->liveness == 0) {
             // poll ended on timeout, $event being false
             if ($this->verbose) {
                 $this->log("WARN", "disconnected from broker - retrying...\n");
             }
             usleep($this->reconnect * 1000);
             $this->connect();
         }
         // Send HEARTBEAT if it's time
         if (microtime(true) > $this->heartbeatAt) {
             $this->send(Mdp::WORKER_HEARTBEAT);
             $this->updateHeartbeatExpiry();
         }
     }
 }
Beispiel #3
0
 /**
  * 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);
         }
     }
 }