protected function launchClient()
{
//We don't even need to start client if queue is empty
if ($this->queue->count() == 0) {
$this->log('DEBUG', "It does not need to start major-domo client as queue is empty.");
return;
}
$this->log('DEBUG', "Launching %s 0mq mdp client", $this->name);
$session = (new AsynClient(\Scalr::config('scalr.crontab.sockets.broker'), true))->setLogger(\Scalr::getContainer()->logger('Mdp\\AsynClient')->setLevel(\Scalr::config('scalr.crontab.log_level')))->setTimeout(\Scalr::config('scalr.crontab.heartbeat.delay') * \Scalr::config('scalr.crontab.heartbeat.liveness') * 2)->connect();
$this->log('DEBUG', 'Sending request messages to broker');
$payloadClass = $this->payloadClass;
//The number of the requests sent
$count = 0;
//Array of the messages which are sent
$sentMessages = [];
//Gets queue iterator in order to gracefully iterate over an ArrayObject removing each offset
$it = $this->queue->getIterator();
//Sending messages loop
while ($it->valid()) {
$key = $it->key();
//Creates standard payload for zmq messaging
$payload = (new $payloadClass($it->current()))->setId();
$sentMessages[$payload->getId()] = $payload;
$request = new Zmsg();
$request->setLast(serialize($payload));
//Sends the message to worker
if ($payload instanceof PayloadRouterInterface) {
$session->send($payload->getAddress($this), $request);
} else {
$session->send($this->name, $request);
}
$count++;
$it->next();
//Removing the message from the queue
$it->offsetUnset($key);
}
//Cleanup queue
unset($this->queue);
$this->log('DEBUG', 'Polling results');
//Receiving loop
for ($i = 0; $i < $count; $i++) {
$msg = $session->recv();
if (!$msg) {
// Interrupt or failure
$this->getLogger()->fatal("Some worker failed!");
break;
}
//We are having deal with serialized data
$payload = @unserialize($msg->getLast());
if (!$payload instanceof AbstractPayload) {
throw new TaskException(sprintf("Unexpected reply from worker: '%s'.", $msg->getLast()));
}
//Checks if worker reaches a memory limit
if (!empty($payload->dw)) {
$this->toDisconnect[$payload->dw] = $payload instanceof PayloadRouterInterface ? $payload->getAddress($this) : $this->name;
$this->log("DEBUG", "Client got PID:%d from the worker %s to disconnect", $payload->dw, $this->toDisconnect[$payload->dw]);
}
if (!isset($sentMessages[$payload->getId()])) {
//Message comes from previous session?
$this->getLogger()->warn("Strange message came from another session. Payload:%s", var_export($payload, true));
$count++;
} else {
//We get response so remove record
unset($sentMessages[$payload->getId()]);
//Triggers onResponse callback
$this->onResponse($payload);
}
}
if (!empty($this->toDisconnect) && $this->config()->daemon) {
foreach ($this->toDisconnect as $pid => $address) {
//Terminates worker
$this->terminateWorker($pid);
//We need to get up a replacement for that one
$pid = $this->addWorker($address);
//It is important to save a PID of the process to be able terminate all workers along with client
$this->pids[$pid] = $pid;
}
//Resets event
$this->toDisconnect = [];
usleep(100000);
}
$this->onCompleted();
}