/** * Constucts object. * * @param callable $callback Callable to call for each consumed event. * @param AMQPStreamConnection $connection AMQP connection object. * @param string $queue Queue to bind. * @param string $exchange An events exchange. * @param string $bindingKey A binding key. * * @throws ErrorException On network\transport errors. */ public function __construct(callable $callback, AMQPStreamConnection $connection, $queue, $exchange, $bindingKey) { // TODO: consumer shoud has own connection with heartbeat. // The heartbeat is checked only during IO operations, so when AMQP connection // not used for a long time, RabbitMQ terminates connection $this->queue = $queue; $this->bindingKey = $bindingKey; $this->channel = $connection->channel(); Util::declareQueue($connection, $queue, ['durable' => true, 'exclusive' => false]); Util::declareExchange($connection, $exchange, 'direct', ['auto_delete' => false]); $ch->queue_bind($queue, $exchange, $bindingKey); $wrapper = function ($msg) use($callback) { $event = new Event($msg); return $callback($event); }; $ch->basic_consume($this->queue, '', false, false, false, false, $wrapper); }
/** * Initializes result objects: creates AMQP objects and binds result queue. * * @return void */ public function initialize() { $this->channel = $this->connection->channel(); // `auto-delete` argument makes sure that queue will be deleted after last queue // consumer disconnected. (Won't be deleted if there weren't any consumers) // `x-expires` queue option means that queue will be deleted if it's unused for the // specified time in milliseconds. Unused means that queue has no consumers, // the queue has not been redeclared, and basic.get has not been invoked. Util::declareQueue($this->connection, $this->taskId, ['exclusive' => false, 'durable' => true, 'auto_delete' => true, 'arguments' => ['x-expires' => self::EXPIRE_TIME]]); Util::declareExchange($this->connection, 'celeryresults', 'direct', ['exclusive' => false]); $this->channel->queue_bind($this->taskId, 'celeryresults', $this->taskId); }
/** * Generic method to synchronously call Fatmouse Agent tasks. * * Create result queue for the task and bind it to results exchange. * Scalr uses agent tasks directly in synchronous manner (mostly for * retrieving server stats), and due to very high request rate we need * to clean up per-task result queues ASAP. * * `auto-delete` argument makes sure that queue will be deleted after last queue * consumer disconnected. (Won't be deleted if there weren't any consumers) * * `x-expires` queue option means that queue will be deleted if it's unused for the * specified time in milliseconds. Unused means that queue has no consumers, * the queue has not been redeclared, and basic.get has not been invoked. * * Example: Call Fatmouse Agent task * <code> * <?php * $serverId = "cf3a320b-7ac6-4b88-810a-c760a94e1875"; * $taskName = "sys.set_hostname"; * $params = ["hostname" => "myexample.com"]; * $timeout = 5; * $result = $fatmouse->callAgentSync($serverId, $taskName, $params, $timeout); * ?> * </code> * * @param string $serverId Scalr server-id to call task at * @param string $taskName Agent task name * @param array $kwargs optional Task parameters * @param integer $timeout optional Result timeout in seconds * @return \stdClass|mixed Task result */ public function callAgentSync($serverId, $taskName, $kwargs = null, $timeout = null) { list($taskId, $serializedTask) = $this->prepareCeleryTask($taskName, $kwargs); $serverExchange = 'server.' . $serverId . '.celery'; $connection = $this->getConnection(); $channel = $connection->channel(); $timeout = $timeout === null ? $this->defaultCallAgentTimeout : $timeout; try { Util::declareQueue($connection, $taskId, ['durable' => false, 'auto_delete' => true, 'arguments' => $timeout ? ['x-expires' => $timeout * 1000] : null]); Util::declareExchange($connection, 'celeryresults', 'direct'); $channel->queue_bind($taskId, 'celeryresults', $taskId); // Sending task to server's queue $msg = new AMQPMessage($serializedTask, $this->publishParams); $channel->basic_publish($msg, $serverExchange); $result = null; $setResult = function ($msg) use(&$result) { $result = Util::jsonDecode($msg->body); }; // Setting callback for message $channel->basic_consume($taskId, '', false, true, false, false, $setResult); try { $channel->wait(null, false, $timeout); } catch (AMQPTimeoutException $e) { throw new Errors\ClientException(sprintf("Timeout %d seconds exceeded while waiting for task '%s' to complete on server '%s'", $timeout, $taskName, $server_id)); } return $result; } finally { $channel->close(); } }