Source of file ClientEndpoint.php

Size: 5,226 Bytes - Last Modified: 2021-01-12T22:04:13+00:00

C:/Users/MAKS/Code/_PROJECTS/amqp-agent/src/RPC/ClientEndpoint.php

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testConnectMethodReturnsSelf
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
4748
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testConnectMethodReturnsSelf
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
49
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testConnectMethodReturnsSelf
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
50
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testConnectMethodReturnsSelf
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
51
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testConnectMethodReturnsSelf
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
52
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testConnectMethodReturnsSelf
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
53
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testConnectMethodReturnsSelf
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
54
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testConnectMethodReturnsSelf
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
555657
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testConnectMethodReturnsSelf
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
58
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testConnectMethodReturnsSelf
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
59
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testConnectMethodReturnsSelf
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
60
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testConnectMethodReturnsSelf
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
61
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testConnectMethodReturnsSelf
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
62
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testConnectMethodReturnsSelf
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
63
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testConnectMethodReturnsSelf
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
6465
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
66
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testConnectMethodReturnsSelf
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
67686970
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testConnectMethodReturnsSelf
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
717273747576777879808182
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodRaisesAnExceptionIfTheClientIsNotConnectedYet
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
83
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodRaisesAnExceptionIfTheClientIsNotConnectedYet
848586
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
87
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
88
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
89
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
90
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
9192
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
93
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
94
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
95
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
9697
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
98
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
99
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
100
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
101
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
102
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
103104105
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
106107
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
108
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
109
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
110
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
111112113
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
114115
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
116
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
117118119
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
120121122123124125126127128129130131132
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
133134135136137138139140141142143
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
144145
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
146
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
147
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
148
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
149150151
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
152
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
153
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
154
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
155
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
156157158159160161162163164165166167
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
168169170
<?php

/**
 * @author Marwan Al-Soltany <MarwanAlsoltany@gmail.com>
 * @copyright Marwan Al-Soltany 2020
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

declare(strict_types=1);

namespace MAKS\AmqpAgent\RPC;

use PhpAmqpLib\Message\AMQPMessage;
use MAKS\AmqpAgent\Helper\ClassProxy;
use MAKS\AmqpAgent\Helper\IDGenerator;
use MAKS\AmqpAgent\RPC\AbstractEndpoint;
use MAKS\AmqpAgent\RPC\ClientEndpointInterface;
use MAKS\AmqpAgent\Exception\RPCEndpointException;

/**
 * A class specialized in requesting. Implementing only the methods needed for a client.
 *
 * Example:
 * ```
 * $clientEndpoint = new ClientEndpoint();
 * $clientEndpoint->on('some.event', function () { ... });
 * $clientEndpoint->connect();
 * $clientEndpoint->request('Message Body', 'queue.name');
 * $clientEndpoint->disconnect();
 * ```
 *
 * @since 2.0.0
 * @api
 */
class ClientEndpoint extends AbstractEndpoint implements ClientEndpointInterface
{
    /**
     * Opens a connection with RabbitMQ server.
     * @param array|null $connectionOptions
     * @return self
     * @throws RPCEndpointException
     */
    public function connect(?array $connectionOptions = [])
    {
        parent::connect($connectionOptions);

        if ($this->isConnected()) {
            list($this->responseQueue, , ) = $this->channel->queue_declare(
                null,
                false,
                false,
                true,
                false
            );

            $this->channel->basic_consume(
                $this->responseQueue,
                null,
                false,
                false,
                false,
                false,
                function ($message) {
                    ClassProxy::call($this, 'onResponse', $message);
                }
            );
        }

        return $this;
    }

    /**
     * Sends the passed request to the server using the passed queue.
     * @param string|AMQPMessage $request The request body or an `AMQPMessage` instance.
     * @param string|null $queueName [optional] The name of queue to send through.
     * @return string The response body.
     * @throws RPCEndpointException If the client is not connected yet or if request Correlation ID does not match the one of the response.
     */
    public function request($request, ?string $queueName = null): string
    {
        if (!$this->isConnected()) {
            throw new RPCEndpointException('Client is not connected yet!');
        }

        $this->queueName = $queueName ?? $this->queueName;
        $this->requestBody = $request instanceof AMQPMessage ? $request->body : (string)$request;
        $this->responseBody = null;
        $this->requestQueue = $this->queueName;
        $this->correlationId = IDGenerator::generateHash();

        $message = $request instanceof AMQPMessage ? $request : new AMQPMessage((string)$request);
        $message->set('reply_to', $this->responseQueue);
        $message->set('correlation_id', $this->correlationId);
        $message->set('timestamp', time());

        $this->channel->queue_declare(
            $this->requestQueue,
            false,
            false,
            false,
            false
        );

        $this->trigger('request.before.send', [$message]);

        $this->channel->basic_publish(
            $message,
            null,
            $this->requestQueue
        );

        $this->trigger('request.after.send', [$message]);

        while ($this->responseBody === null) {
            $this->channel->wait();
        }

        return $this->responseBody;
    }

    /**
     * Sends the passed request to the server using the passed queue.
     * Alias for `self::request()`.
     * @param string|AMQPMessage $request The request body or an `AMQPMessage` instance.
     * @param string|null $queueName [optional] The name of queue to send through.
     * @return string The response body.
     * @throws RPCEndpointException If the client is not connected yet or if request Correlation ID does not match the one of the response.
     */
    public function call($request, ?string $queueName = null): string
    {
        return $this->request($request, $queueName);
    }

    /**
     * Validates the response.
     * @param AMQPMessage $response
     * @return void
     * @throws RPCEndpointException
     */
    protected function onResponse(AMQPMessage $response): void
    {
        $this->trigger('response.on.get', [$response]);

        if ($this->correlationId === $response->get('correlation_id')) {
            $this->responseBody = $this->callback($response);
            $response->ack();
            return;
        }

        throw new RPCEndpointException(
            sprintf(
                'Correlation ID of the response "%s" does not match the one of the request "%s"!',
                $this->correlationId,
                (string)$response->get('correlation_id')
            )
        );
    }

    /**
     * Returns the final response body.
     * @param AMQPMessage $message
     * @return string
     */
    protected function callback(AMQPMessage $message): string
    {
        return $message->body;
    }
}