public function callback(AMQPMessage $msg) { $routingKey = $msg->delivery_info['routing_key']; $method = 'read' . Inflector::camelize($routingKey); if (!isset($this->interpreters[$this->exchange])) { $interpreter = $this; } elseif (class_exists($this->interpreters[$this->exchange])) { $interpreter = new $this->interpreters[$this->exchange](); if (!$interpreter instanceof AmqpInterpreter) { throw new Exception(sprintf("Class '%s' is not correct interpreter class.", $this->interpreters[$this->exchange])); } } else { throw new Exception(sprintf("Interpreter class '%s' was not found.", $this->interpreters[$this->exchange])); } if (method_exists($interpreter, $method)) { $info = ['exchange' => $msg->get('exchange'), 'routing_key' => $msg->get('routing_key'), 'reply_to' => $msg->has('reply_to') ? $msg->get('reply_to') : null]; $interpreter->{$method}(Json::decode($msg->body, true), $info); } else { if (!isset($this->interpreters[$this->exchange])) { $interpreter = new AmqpInterpreter(); } $interpreter->log(sprintf("Unknown routing key '%s' for exchange '%s'.", $routingKey, $this->exchange), $interpreter::MESSAGE_ERROR); // debug the message $interpreter->log(print_r(Json::decode($msg->body, true), true), $interpreter::MESSAGE_INFO); } }
public function callback(AMQPMessage $msg) { $routingKey = $msg->get('routing_key'); $method = 'read' . Inflector::camelize($routingKey); $interpreter = isset($this->interpreters[$this->exchange]) ? $this->interpreters[$this->exchange] : (isset($this->interpreters['*']) ? $this->interpreters['*'] : null); if ($interpreter === null) { $interpreter = $this; } else { if (class_exists($interpreter)) { $interpreter = new $interpreter(); if (!$interpreter instanceof AmqpInterpreter) { throw new Exception(sprintf("Class '%s' is not correct interpreter class.", $interpreter)); } } else { throw new Exception(sprintf("Interpreter class '%s' was not found.", $interpreter)); } } if (method_exists($interpreter, $method) || is_callable([$interpreter, $method])) { $info = ['exchange' => $this->exchange, 'routing_key' => $routingKey, 'reply_to' => $msg->has('reply_to') ? $msg->get('reply_to') : null, 'delivery_tag' => $msg->get('delivery_tag')]; try { $body = Json::decode($msg->body, true); } catch (\Exception $e) { $body = $msg->body; } $interpreter->{$method}($body, $info, $this->amqp->channel); } else { if (!$interpreter instanceof AmqpInterpreter) { $interpreter = new AmqpInterpreter(); } $interpreter->log(sprintf("Unknown routing key '%s' for exchange '%s'.", $routingKey, $this->exchange), $interpreter::MESSAGE_ERROR); // debug the message $interpreter->log(print_r(Json::decode($msg->body, true), true), $interpreter::MESSAGE_INFO); } }
/** * @param AMQPMessage $amqpMessage The message to convert * * @return MessageInterface */ public static function toMessage(AMQPMessage $amqpMessage) { $properties = array('content_type', 'content_encoding', 'app_id', 'correlation_id', 'delivery_tag', 'message_id', 'priority', 'reply_to', 'routing_key', 'exchange_name', 'timestamp', 'type', 'user_id'); $propertyValues = array_map(function ($propertyName) use($amqpMessage) { if ($amqpMessage->has($propertyName)) { return $amqpMessage->get($propertyName); } return false; }, $properties); $headers = $amqpMessage->has('application_headers') ? $amqpMessage->get('application_headers')->getNativeData() : array(); $message = new \Amqp\Message(); $message->setPayload($amqpMessage->body)->setDeliveryMode($amqpMessage->get('delivery_mode'))->setHeaders($headers)->setProperties(array_combine($properties, $propertyValues)); return $message; }
/** * @param AMQPMessage $message * * @return AMQPTable */ private function getHeaders(AMQPMessage $message) { if ($message->has('application_headers')) { return $message->get('application_headers'); } return new AMQPTable(); }
/** * @param string $name * @return string */ private function getFromEnvelope(string $name) : string { if ($this->envelope->has($name)) { return $this->envelope->get($name); } return ''; }
public function execute(AMQPMessage $msg) { $body = json_decode($msg->body, true); if ($msg->has("application_headers")) { $nativeData = $msg->get("application_headers")->getNativeData(); } return $this->readMessage($body, isset($nativeData['attempts']) ? $nativeData['attempts'] : 0); }
/** * @param AMQPMessage $queueMessage * * @return $this */ protected function setPropertiesFromMessage($queueMessage) { foreach ($this->propertyMapping as $mqlibProperty => $amqpProperty) { if ($queueMessage->has($amqpProperty) && property_exists($this, $mqlibProperty)) { $this->{$mqlibProperty} = $amqpProperty; } } return $this; }
/** * @param AmqpLibMessage $message * * @return AmqpMessage */ public static function createMessage(AmqpLibMessage $message) { $properties = ['body' => $message->body]; foreach (self::$PROPERTY_MAP as $name => $amqpLibName) { if ($message->has($amqpLibName)) { $properties[$name] = $message->get($amqpLibName); } } return CustomAmqpMessage::fromProperties($properties); }
/** * @param AMQPMessage $message * * @return Request * * @throws \Exception */ private function createRequest(AMQPMessage $message) { $topic = $message->delivery_info['routing_key']; $headers = $message->has('application_headers') ? $message->get('application_headers')->getNativeData() : []; $version = isset($headers['version']) ? $headers['version'] : null; $arguments = json_decode($message->getBody(), true); if (json_last_error() !== JSON_ERROR_NONE) { throw new EncodingException('Unable to decode request: ' . json_last_error_msg()); } return new Request($topic, $version, $arguments, $headers); }
public function callback(AMQPMessage $Message) { try { $result = $Message->delivery_info['delivery_tag']; // отправляем ответ, если он вообще нужен if ($Message->has('reply_to')) { $Message->delivery_info['channel']->basic_publish(new AMQPMessage($this->_encode($result), ['correlation_id' => $Message->get('correlation_id')]), '', $Message->get('reply_to')); } // подтверждаем $Message->delivery_info['channel']->basic_ack($Message->delivery_info['delivery_tag']); } catch (\Exception $e) { $Message->delivery_info['channel']->basic_nack($Message->delivery_info['delivery_tag']); } }
public function execute(AMQPMessage $msg) { if (!$msg->has('application_headers') || !isset($msg->get('application_headers')['x-death'])) { sleep(2); return false; } $message = json_decode($msg->body, true); /* Отправка задачи на исполнение */ $producer = $this->container->get('old_sound_rabbit_mq.' . $message['producer'] . '_producer'); if (isset($message['route'])) { $producer->publish($message['payload'], $message['route']); } else { $producer->publish($message['payload']); } /* Установка задачи с задержкой */ if ($message['recurring']) { $this->sheduleJob($message); } return true; }
/** * Handles a task. * * @param mixed $message */ private function taskHandler(AMQPMessage $message) { /** @var AMQPChannel $channel */ $channel = $message->delivery_info['channel']; // Listen to the "reply_to" queue $replyExchange = null; $replyQueue = null; if ($message->has('reply_to')) { list($replyExchange, $replyQueue) = explode(';', $message->get('reply_to')); } /** @var Task $task */ $task = unserialize($message->body); try { $this->triggerEvent(self::EVENT_AFTER_TASK_UNSERIALIZATION, [$task]); $this->triggerEvent(self::EVENT_BEFORE_TASK_EXECUTION, [$task]); // Execute the task $this->getExecutor($task)->execute($task); $this->triggerEvent(self::EVENT_BEFORE_TASK_FINISHED, [$task]); $success = true; $e = null; } catch (Exception $e) { $success = false; } // Signal the job status to RabbitMQ if ($success) { $channel->basic_ack($message->delivery_info['delivery_tag']); } else { $channel->basic_reject($message->delivery_info['delivery_tag'], false); } $dispatcherNotified = false; // Signal the job status to the dispatcher if ($replyExchange) { $message = $success ? 'finished' : 'errored'; $dispatcherNotified = $this->notifyDispatcher($replyExchange, $replyQueue, $message); } if ($success) { $this->triggerEvent(self::EVENT_ON_TASK_SUCCESS, [$task, $dispatcherNotified]); } else { $this->triggerEvent(self::EVENT_ON_TASK_ERROR, [$task, $e, $dispatcherNotified]); } }
/** * Handles a message. * * @param mixed $message */ public function handle(AMQPMessage $message) { /** @var AMQPChannel $channel */ $channel = $message->delivery_info['channel']; // Listen to the "reply_to" queue $replyExchange = null; $replyQueue = null; if ($message->has('reply_to')) { list($replyExchange, $replyQueue) = explode(';', $message->get('reply_to')); } $this->trigger(IWorker::BEFORE_UNSERIALIZATION, [$message]); $envelope = unserialize($message->body); try { // Execute the handler; consume the message $this->trigger(IWorker::BEFORE_CONSUMING, [$envelope]); $this->consume($envelope); $this->trigger(IWorker::AFTER_CONSUMING, [$envelope]); $success = true; $e = null; } catch (\Exception $e) { $success = false; } // Signal the job status to RabbitMQ if ($success) { $channel->basic_ack($message->delivery_info['delivery_tag']); } else { $channel->basic_reject($message->delivery_info['delivery_tag'], false); } $dispatcherNotified = false; // Signal the job status to the dispatcher if ($replyExchange) { $message = $success ? 'finished' : 'errored'; $dispatcherNotified = $this->notifyDispatcher($replyExchange, $replyQueue, $message); } if ($success) { $this->trigger(IWorker::ON_HANDLER_SUCCESS, [$envelope, $dispatcherNotified]); } else { $this->trigger(IWorker::ON_HANDLER_ERROR, [$envelope, $e, $dispatcherNotified]); } }
public function callback(AMQPMessage $msg) { $routingKey = $msg->delivery_info['routing_key']; $method = 'read' . Inflector::camelize($routingKey); if (!isset($this->interpreters[$this->queue])) { $interpreter = $this; } elseif (class_exists($this->interpreters[$this->queue])) { $interpreter = new $this->interpreters[$this->queue](); if (!$interpreter instanceof AmqpInterpreter) { throw new Exception(sprintf("Class '%s' is not correct interpreter class.", $this->interpreters[$this->queue])); } } else { throw new Exception(sprintf("Interpreter class '%s' was not found.", $this->interpreters[$this->queue])); } if (method_exists($interpreter, $method)) { $info = ['exchange' => $msg->get('exchange'), 'queue' => $this->queue, 'routing_key' => $msg->get('routing_key'), 'reply_to' => $msg->has('reply_to') ? $msg->get('reply_to') : null]; try { $interpreter->{$method}(Json::decode($msg->body, true), $info); } catch (\Exception $exc) { $error_info = "consumer fail:" . $exc->getMessage() . PHP_EOL . "info:" . print_r($info, true) . PHP_EOL . "body:" . PHP_EOL . print_r($msg->body, true) . PHP_EOL . $exc->getTraceAsString(); \Yii::warning($error_info, __METHOD__); $format = [Console::FG_RED]; Console::stdout(Console::ansiFormat($error_info . PHP_EOL, $format)); Console::stdout(Console::ansiFormat($exc->getTraceAsString() . PHP_EOL, $format)); } } else { if (!isset($this->interpreters[$this->queue])) { $interpreter = new AmqpInterpreter(); } $error_info = "Unknown routing key '{$routingKey}' for exchange '{$this->queue}'."; $error_info .= PHP_EOL . $msg->body; \Yii::warning($error_info, __METHOD__); $interpreter->log(sprintf("Unknown routing key '%s' for exchange '%s'.", $routingKey, $this->queue), $interpreter::MESSAGE_ERROR); // debug the message $interpreter->log(print_r(Json::decode($msg->body, true), true), $interpreter::MESSAGE_INFO); } }
/** * @param AMQPMessage $message * @param string $header * * @return string|null */ private function getMessageHeader(AMQPMessage $message, $header) { $headers = $message->has('application_headers') ? $message->get('application_headers') : []; return array_key_exists($header, $headers) ? $headers[$header] : null; }
/** * Build AMQPEnvelope from a php-amqplib message; * * @param AMQPMessage $message * @return AMQPEnvelope */ public static function fromAMQPMessage(AMQPMessage $message) { $envelope = new self(); $envelope->app_id = $message->has('app_id') ? $message->get('app_id') : ''; $envelope->body = $message->body; $envelope->content_encoding = $message->has('content_encoding') ? $message->get('content_encoding') : ''; $envelope->content_type = $message->has('content_type') ? $message->get('content_type') : ''; $envelope->correlation_id = $message->has('correlation_id') ? $message->get('correlation_id') : ''; $envelope->delivery_mode = $message->has('delivery_mode') ? $message->get('delivery_mode') : ''; $envelope->delivery_tag = $message->has('delivery_tag') ? $message->get('delivery_tag') : ''; $envelope->exchange_name = $message->has('exchange') ? $message->get('exchange') : ''; $envelope->expiration = $message->has('expiration') ? $message->get('expiration') : ''; $envelope->headers = $message->has('application_headers') ? $message->get('application_headers')->getNativeData() : ''; $envelope->message_id = $message->has('message_id') ? $message->get('message_id') : ''; $envelope->priority = $message->has('priority') ? $message->get('priority') : ''; $envelope->reply_to = $message->has('reply_to') ? $message->get('reply_to') : ''; $envelope->routing_key = $message->has('routing_key') ? $message->get('routing_key') : ''; $envelope->timestamp = $message->has('timestamp') ? $message->get('timestamp') : ''; $envelope->type = $message->has('type') ? $message->get('type') : ''; $envelope->user_id = $message->has('user_id') ? $message->get('user_id') : ''; $envelope->is_redelivery = $message->has('redelivered') ? $message->get('redelivered') : ''; return $envelope; }
/** * @param AMQPMessage $libMessage * @return Message * @throws \OutOfBoundsException */ public function toMessage(AMQPMessage $libMessage) { $message = clone $this->getMessagePrototype(); $message->setBody($libMessage->getBody()); $message->setRoutingKey($libMessage->get($libMessage->has('routing_key') ? 'routing_key' : null)); $message->setDeliveryTag($libMessage->has('delivery_tag') ? $libMessage->get('delivery_tag') : null); $message->setDeliveryMode($libMessage->has('delivery_mode') ? $libMessage->get('delivery_mode') : null); $message->setExchangeName($libMessage->has('exchange') ? $libMessage->get('exchange') : null); $message->setRedelivered($libMessage->has('redelivered') ? $libMessage->get('redelivered') : false); $message->setContentType($libMessage->has('content_type') ? $libMessage->get('content_type') : null); $message->setContentEncoding($libMessage->has('content_encoding') ? $libMessage->get('content_encoding') : null); $message->setType($libMessage->has('type') ? $libMessage->get('type') : null); $message->setDateTime($libMessage->has('timestamp') ? (new DateTime())->setTimestamp($libMessage->get('timestamp')) : null); $message->setPriority($libMessage->has('priority') ? $libMessage->get('priority') : null); $expiration = $libMessage->has('expiration') ? $libMessage->get('expiration') : null; $message->setExpiration(!empty($expiration) ? new \DateTime($libMessage->get('expiration')) : null); $message->setUserId($libMessage->has('user_id') ? $libMessage->get('user_id') : null); $message->setAppId($libMessage->has('app_id') ? $libMessage->get('app_id') : null); $message->setMessageId($libMessage->has('message_id') ? $libMessage->get('message_id') : null); $message->setReplyTo($libMessage->has('reply_to') ? $libMessage->get('reply_to') : null); $message->setCorrelationId($libMessage->has('correlation_id') ? $libMessage->get('correlation_id') : null); $message->setHeaders($libMessage->has('application_headers') ? $libMessage->get('application_headers') : []); return $message; }
/** * @param \PhpAmqpLib\Message\AMQPMessage $message * @param string $exchange * @param string $routingKey * * @throws RuntimeException * @throws Exception|PhpAmqpLib\Exception\AMQPTimeoutException * @return mixed */ protected function doSendAndReceive(\PhpAmqpLib\Message\AMQPMessage $message, $exchange, $routingKey) { if ($message->has('correlation_id')) { throw new RuntimeException('Illegal API usage. RPC style exchange can only be used if no correlationId property is set on beforehand.'); } if ($message->has('reply_to')) { throw new RuntimeException('Illegal API usage. RPC style exchange can only be used if no replyTo property is set on beforehand.'); } $replyQueue = $this->replyQueue; $replyTimeoutInMs = $this->replyTimeoutInMs; $mandatory = $this->mandatory; $immediate = $this->immediate; return $this->execute(function (\PhpAmqpLib\Channel\AMQPChannel $channel) use($message, $exchange, $routingKey, $replyQueue, $replyTimeoutInMs, $mandatory, $immediate) { $correlationId = Tx_Amqp_Util_Randomizer::generateUUID(); if ($replyQueue === NULL) { // create a temporary (non-durable) exclusive auto-delete reply-queue list($replyQueue, , ) = $channel->queue_declare('', FALSE, FALSE, TRUE, TRUE); } $message->set('reply_to', $replyQueue); $message->set('correlation_id', $correlationId); $response = NULL; $callback = function (\PhpAmqpLib\Message\AMQPMessage $message) use($channel, $correlationId, &$response) { if ($correlationId == $message->get('correlation_id')) { $channel->basic_ack($message->delivery_info['delivery_tag']); $message->delivery_info['channel']->basic_cancel($message->delivery_info['consumer_tag']); $response = $message->body; } }; $channel->basic_consume($replyQueue, '', FALSE, FALSE, FALSE, FALSE, $callback); $channel->basic_publish($message, $exchange, $routingKey, $mandatory, $immediate); while (count($channel->callbacks)) { try { $channel->wait(NULL, FALSE, (double) $replyTimeoutInMs / 1000.0); } catch (\PhpAmqpLib\Exception\AMQPTimeoutException $e) { // TODO: convert to own exception hierarchy? throw $e; } } return $response; }); }
/** * @param AMQPMessage $message * * @return Response * * @throws ReplyException */ private function createResponse(AMQPMessage $message) { $headers = $message->has('application_headers') ? $message->get('application_headers')->getNativeData() : []; if (!empty($headers['x-error'])) { throw new ReplyException($headers['x-error'], isset($headers['x-error-code']) ? $headers['x-error-code'] : 0); } $type = $message->has('content_type') ? $message->get('content_type') : null; $value = $this->encoder->decode(new Encoded($type, $message->getBody())); return new Response($value, $headers); }
/** * @param AMQPMessage $message */ public function consume(AMQPMessage $message) { $context = []; if ($message->has('correlation_id')) { $context['correlation_id'] = $message->get('correlation_id'); } if ($this->logger) { $this->logger->info('received message with content-type ' . $message->get('content_type'), $context); } $contentType = new StringLiteral($message->get('content_type')); try { $deserializer = $this->deserializerLocator->getDeserializerForContentType($contentType); $domainMessage = $deserializer->deserialize(new StringLiteral($message->body)); // If the deserializer did not return a DomainMessage yet, then // consider the returned value as the payload, and wrap it in a // DomainMessage. if (!$domainMessage instanceof DomainMessage) { $domainMessage = new DomainMessage(UUID::generateAsString(), 0, new Metadata($context), $domainMessage, DateTime::now()); } $this->delayIfNecessary(); if ($this->logger) { $this->logger->info('passing on message to event bus', $context); } $this->eventBus->publish(new DomainEventStream([$domainMessage])); } catch (\Exception $e) { if ($this->logger) { $this->logger->error($e->getMessage(), $context + ['exception' => $e]); } $message->delivery_info['channel']->basic_reject($message->delivery_info['delivery_tag'], false); if ($this->logger) { $this->logger->info('message rejected', $context); } return; } $message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']); if ($this->logger) { $this->logger->info('message acknowledged', $context); } }