diff --git a/bin/changelog b/bin/changelog index 8a9296175..ba2db0813 100755 --- a/bin/changelog +++ b/bin/changelog @@ -8,6 +8,6 @@ then exit 1 fi -docker-compose run -e CHANGELOG_GITHUB_TOKEN=${CHANGELOG_GITHUB_TOKEN:-""} --workdir="/mqdev" --rm generate-changelog github_changelog_generator --future-release "$1" --no-issues --unreleased-only --output "CHANGELOG_FUTURE.md" +docker compose run -e CHANGELOG_GITHUB_TOKEN=${CHANGELOG_GITHUB_TOKEN:-""} --workdir="/mqdev" --rm generate-changelog github_changelog_generator --future-release "$1" --no-issues --unreleased-only --output "CHANGELOG_FUTURE.md" -#git add CHANGELOG.md && git commit -m "Release $1" -S && git push origin "$CURRENT_BRANCH" \ No newline at end of file + git add CHANGELOG.md && git commit -m "Release $1" -S && git push origin "$CURRENT_BRANCH" diff --git a/bin/dev b/bin/dev index a50b7ad66..45a3e7124 100755 --- a/bin/dev +++ b/bin/dev @@ -6,13 +6,13 @@ set -e while getopts "bustefdp" OPTION; do case $OPTION in b) - docker-compose pull -q && docker-compose build + docker compose pull -q && docker compose build ;; u) - docker-compose up + docker compose up ;; s) - docker-compose stop + docker compose stop ;; e) docker exec -it mqdev_dev_1 /bin/bash @@ -21,7 +21,7 @@ while getopts "bustefdp" OPTION; do ./bin/php-cs-fixer fix ;; - d) docker-compose run --workdir="/mqdev" --rm dev php pkg/enqueue-bundle/Tests/Functional/app/console.php config:dump-reference enqueue -vvv + d) docker compose run --workdir="/mqdev" --rm dev php pkg/enqueue-bundle/Tests/Functional/app/console.php config:dump-reference enqueue -vvv ;; \?) echo "Invalid option: -$OPTARG" >&2 diff --git a/bin/test.sh b/bin/test.sh index f392e616b..5cb858ad6 100755 --- a/bin/test.sh +++ b/bin/test.sh @@ -3,4 +3,4 @@ set -x set -e -docker-compose run --workdir="/mqdev" --rm dev ./docker/bin/test.sh $@ +docker compose run --workdir="/mqdev" --rm dev ./docker/bin/test.sh $@ diff --git a/composer.json b/composer.json index 5c0108e27..e17ab6570 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ "doctrine/persistence": "^2.0|^3.0", "mongodb/mongodb": "^1.2", "pda/pheanstalk": "^3.1", - "aws/aws-sdk-php": "^3.155", + "aws/aws-sdk-php": "^3.290", "stomp-php/stomp-php": "^4.5|^5", "php-http/guzzle7-adapter": "^0.1.1", "php-http/client-common": "^2.2.1", @@ -137,4 +137,3 @@ } } } - diff --git a/docker-compose.yml b/docker-compose.yml index c5fa5545b..a5b884b31 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -38,16 +38,16 @@ services: - PREDIS_DSN=redis+predis://redis - PHPREDIS_DSN=redis+phpredis://redis - GPS_DSN=gps:?projectId=mqdev&emulatorHost=http://google-pubsub:8085 - - SQS_DSN=sqs:?key=key&secret=secret®ion=us-east-1&endpoint=http://localstack:4576&version=latest - - SNS_DSN=sns:?key=key&secret=secret®ion=us-east-1&endpoint=http://localstack:4575&version=latest - - SNSQS_DSN=snsqs:?key=key&secret=secret®ion=us-east-1&sns_endpoint=http://localstack:4575&sqs_endpoint=http://localstack:4576&version=latest + - SQS_DSN=sqs:?key=key&secret=secret®ion=us-east-1&endpoint=http://localstack:4566&version=latest + - SNS_DSN=sns:?key=key&secret=secret®ion=us-east-1&endpoint=http://localstack:4566&version=latest + - SNSQS_DSN=snsqs:?key=key&secret=secret®ion=us-east-1&sns_endpoint=http://localstack:4566&sqs_endpoint=http://localstack:4566&version=latest - WAMP_DSN=wamp://thruway:9090 - REDIS_HOST=redis - REDIS_PORT=6379 - AWS_SQS_KEY=key - AWS_SQS_SECRET=secret - AWS_SQS_REGION=us-east-1 - - AWS_SQS_ENDPOINT=http://localstack:4576 + - AWS_SQS_ENDPOINT=http://localstack:4566 - AWS_SQS_VERSION=latest - BEANSTALKD_DSN=beanstalk://beanstalkd:11300 - GEARMAN_DSN=gearman://gearmand:4730 @@ -83,6 +83,7 @@ services: mysql: image: mysql:5.7 + platform: linux/amd64 environment: MYSQL_ROOT_PASSWORD: rootpass MYSQL_DATABASE: mqdev @@ -127,13 +128,13 @@ services: - '9090:9090' localstack: - image: 'localstack/localstack:0.8.10' + image: 'localstack/localstack:3.6.0' ports: - - '4576:4576' - - '4575:4575' + - "127.0.0.1:4566:4566" # LocalStack Gateway + - "127.0.0.1:4510-4559:4510-4559" # external services port range environment: HOSTNAME_EXTERNAL: 'localstack' - SERVICES: 'sqs,sns' + SERVICES: 's3,sqs,sns' influxdb: image: 'influxdb:latest' diff --git a/docker/bin/test.sh b/docker/bin/test.sh index 2070584bb..cfc94aab5 100755 --- a/docker/bin/test.sh +++ b/docker/bin/test.sh @@ -39,7 +39,7 @@ waitForService gearmand 4730 50 waitForService kafka 9092 50 waitForService mongo 27017 50 waitForService thruway 9090 50 -waitForService localstack 4576 50 +waitForService localstack 4566 50 php docker/bin/refresh-mysql-database.php || exit 1 php docker/bin/refresh-postgres-database.php || exit 1 diff --git a/docs/contribution.md b/docs/contribution.md index 455f6950e..68d051fc5 100644 --- a/docs/contribution.md +++ b/docs/contribution.md @@ -49,6 +49,6 @@ Once everything is done open a pull request on official repository. ## WTF?! -* If you get `rabbitmqssl: forward host lookup failed: Unknown host, wait for service rabbitmqssl:5671` do `docker-compose down`. +* If you get `rabbitmqssl: forward host lookup failed: Unknown host, wait for service rabbitmqssl:5671` do `docker compose down`. [back to index](index.md) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 1cd38e68b..f5ba01d8f 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -68,10 +68,6 @@ pkg/sns/Tests - - pkg/snsqs/Tests - - pkg/pheanstalk/Tests @@ -123,6 +119,10 @@ pkg/monitoring/Tests + + + pkg/snsqs/Tests + diff --git a/pkg/amqp-ext/Tests/Functional/AmqpCommonUseCasesTest.php b/pkg/amqp-ext/Tests/Functional/AmqpCommonUseCasesTest.php index a90b1d306..ee53ad90b 100644 --- a/pkg/amqp-ext/Tests/Functional/AmqpCommonUseCasesTest.php +++ b/pkg/amqp-ext/Tests/Functional/AmqpCommonUseCasesTest.php @@ -112,6 +112,7 @@ public function testProduceAndReceiveOneMessageSentDirectlyToTemporaryQueue() $queue = $this->amqpContext->createTemporaryQueue(); $message = $this->amqpContext->createMessage(__METHOD__); + $message->setDeliveryTag(145); $producer = $this->amqpContext->createProducer(); $producer->send($queue, $message); @@ -137,6 +138,7 @@ public function testProduceAndReceiveOneMessageSentDirectlyToTopic() $this->amqpContext->bind(new AmqpBind($topic, $queue)); $message = $this->amqpContext->createMessage(__METHOD__); + $message->setDeliveryTag(145); $producer = $this->amqpContext->createProducer(); $producer->send($topic, $message); @@ -158,10 +160,11 @@ public function testConsumerReceiveMessageFromTopicDirectly() $this->amqpContext->declareTopic($topic); $consumer = $this->amqpContext->createConsumer($topic); - //guard + // guard $this->assertNull($consumer->receive(1000)); $message = $this->amqpContext->createMessage(__METHOD__); + $message->setDeliveryTag(145); $producer = $this->amqpContext->createProducer(); $producer->send($topic, $message); @@ -181,10 +184,11 @@ public function testConsumerReceiveMessageWithZeroTimeout() $this->amqpContext->declareTopic($topic); $consumer = $this->amqpContext->createConsumer($topic); - //guard + // guard $this->assertNull($consumer->receive(1000)); $message = $this->amqpContext->createMessage(__METHOD__); + $message->setDeliveryTag(145); $producer = $this->amqpContext->createProducer(); $producer->send($topic, $message); @@ -205,6 +209,7 @@ public function testPurgeMessagesFromQueue() $consumer = $this->amqpContext->createConsumer($queue); $message = $this->amqpContext->createMessage(__METHOD__); + $message->setDeliveryTag(145); $producer = $this->amqpContext->createProducer(); $producer->send($queue, $message); diff --git a/pkg/gps/GpsMessage.php b/pkg/gps/GpsMessage.php index b4a11dc5a..684a7ba7b 100644 --- a/pkg/gps/GpsMessage.php +++ b/pkg/gps/GpsMessage.php @@ -24,6 +24,11 @@ class GpsMessage implements Message, \JsonSerializable */ private $headers; + /** + * @var array + */ + private $attributes; + /** * @var bool */ @@ -34,11 +39,12 @@ class GpsMessage implements Message, \JsonSerializable */ private $nativeMessage; - public function __construct(string $body = '', array $properties = [], array $headers = []) + public function __construct(string $body = '', array $properties = [], array $headers = [], array $attributes = []) { $this->body = $body; $this->properties = $properties; $this->headers = $headers; + $this->attributes = $attributes; $this->redelivered = false; } @@ -103,7 +109,7 @@ public function isRedelivered(): bool return $this->redelivered; } - public function setCorrelationId(string $correlationId = null): void + public function setCorrelationId(?string $correlationId = null): void { $this->setHeader('correlation_id', $correlationId); } @@ -113,7 +119,7 @@ public function getCorrelationId(): ?string return $this->getHeader('correlation_id'); } - public function setMessageId(string $messageId = null): void + public function setMessageId(?string $messageId = null): void { $this->setHeader('message_id', $messageId); } @@ -130,12 +136,12 @@ public function getTimestamp(): ?int return null === $value ? null : (int) $value; } - public function setTimestamp(int $timestamp = null): void + public function setTimestamp(?int $timestamp = null): void { $this->setHeader('timestamp', $timestamp); } - public function setReplyTo(string $replyTo = null): void + public function setReplyTo(?string $replyTo = null): void { $this->setHeader('reply_to', $replyTo); } @@ -151,6 +157,7 @@ public function jsonSerialize(): array 'body' => $this->getBody(), 'properties' => $this->getProperties(), 'headers' => $this->getHeaders(), + 'attributes' => $this->getAttributes(), ]; } @@ -161,7 +168,7 @@ public static function jsonUnserialize(string $json): self throw new \InvalidArgumentException(sprintf('The malformed json given. Error %s and message %s', json_last_error(), json_last_error_msg())); } - return new self($data['body'] ?? $json, $data['properties'] ?? [], $data['headers'] ?? []); + return new self($data['body'] ?? $json, $data['properties'] ?? [], $data['headers'] ?? [], $data['attributes'] ?? []); } public function getNativeMessage(): ?GoogleMessage @@ -169,8 +176,18 @@ public function getNativeMessage(): ?GoogleMessage return $this->nativeMessage; } - public function setNativeMessage(GoogleMessage $message = null): void + public function setNativeMessage(?GoogleMessage $message = null): void { $this->nativeMessage = $message; } + + public function setAttributes(array $attributes): void + { + $this->attributes = $attributes; + } + + public function getAttributes(): array + { + return $this->attributes; + } } diff --git a/pkg/gps/GpsProducer.php b/pkg/gps/GpsProducer.php index 86c9052c0..b36fad19d 100644 --- a/pkg/gps/GpsProducer.php +++ b/pkg/gps/GpsProducer.php @@ -37,12 +37,17 @@ public function send(Destination $destination, Message $message): void /** @var Topic $topic */ $topic = $this->context->getClient()->topic($destination->getTopicName()); - $topic->publish([ - 'data' => json_encode($message), - ]); + + $params = ['data' => json_encode($message)]; + + if (count($message->getAttributes()) > 0) { + $params['attributes'] = $message->getAttributes(); + } + + $topic->publish($params); } - public function setDeliveryDelay(int $deliveryDelay = null): Producer + public function setDeliveryDelay(?int $deliveryDelay = null): Producer { if (null === $deliveryDelay) { return $this; @@ -56,7 +61,7 @@ public function getDeliveryDelay(): ?int return null; } - public function setPriority(int $priority = null): Producer + public function setPriority(?int $priority = null): Producer { if (null === $priority) { return $this; @@ -70,7 +75,7 @@ public function getPriority(): ?int return null; } - public function setTimeToLive(int $timeToLive = null): Producer + public function setTimeToLive(?int $timeToLive = null): Producer { if (null === $timeToLive) { return $this; diff --git a/pkg/gps/Tests/GpsMessageTest.php b/pkg/gps/Tests/GpsMessageTest.php index a43a22315..ee9e652cd 100644 --- a/pkg/gps/Tests/GpsMessageTest.php +++ b/pkg/gps/Tests/GpsMessageTest.php @@ -18,18 +18,18 @@ public function testCouldSetGetNativeMessage() public function testColdBeSerializedToJson() { - $message = new GpsMessage('theBody', ['thePropFoo' => 'thePropFooVal'], ['theHeaderFoo' => 'theHeaderFooVal']); + $message = new GpsMessage('theBody', ['thePropFoo' => 'thePropFooVal'], ['theHeaderFoo' => 'theHeaderFooVal'], ['theAttributeFoo' => 'theAttributeFooVal']); - $this->assertEquals('{"body":"theBody","properties":{"thePropFoo":"thePropFooVal"},"headers":{"theHeaderFoo":"theHeaderFooVal"}}', json_encode($message)); + $this->assertEquals('{"body":"theBody","properties":{"thePropFoo":"thePropFooVal"},"headers":{"theHeaderFoo":"theHeaderFooVal"},"attributes":{"theAttributeFoo":"theAttributeFooVal"}}', json_encode($message)); } public function testCouldBeUnserializedFromJson() { - $message = new GpsMessage('theBody', ['thePropFoo' => 'thePropFooVal'], ['theHeaderFoo' => 'theHeaderFooVal']); + $message = new GpsMessage('theBody', ['thePropFoo' => 'thePropFooVal'], ['theHeaderFoo' => 'theHeaderFooVal'], ['theAttributeFoo' => 'theAttributeFooVal']); $json = json_encode($message); - //guard + // guard $this->assertNotEmpty($json); $unserializedMessage = GpsMessage::jsonUnserialize($json); @@ -40,7 +40,7 @@ public function testCouldBeUnserializedFromJson() public function testMessageEntityCouldBeUnserializedFromJson() { - $json = '{"body":"theBody","properties":{"thePropFoo":"thePropFooVal"},"headers":{"theHeaderFoo":"theHeaderFooVal"}}'; + $json = '{"body":"theBody","properties":{"thePropFoo":"thePropFooVal"},"headers":{"theHeaderFoo":"theHeaderFooVal"},"attributes":{"theAttributeFoo":"theAttributeFooVal"}}'; $unserializedMessage = GpsMessage::jsonUnserialize($json); @@ -49,6 +49,7 @@ public function testMessageEntityCouldBeUnserializedFromJson() $this->assertEquals($decoded['body'], $unserializedMessage->getBody()); $this->assertEquals($decoded['properties'], $unserializedMessage->getProperties()); $this->assertEquals($decoded['headers'], $unserializedMessage->getHeaders()); + $this->assertEquals($decoded['attributes'], $unserializedMessage->getAttributes()); } public function testMessagePayloadCouldBeUnserializedFromJson() @@ -61,6 +62,7 @@ public function testMessagePayloadCouldBeUnserializedFromJson() $this->assertEquals($json, $unserializedMessage->getBody()); $this->assertEquals([], $unserializedMessage->getProperties()); $this->assertEquals([], $unserializedMessage->getHeaders()); + $this->assertEquals([], $unserializedMessage->getAttributes()); } public function testThrowIfMalformedJsonGivenOnUnsterilizedFromJson() @@ -70,4 +72,13 @@ public function testThrowIfMalformedJsonGivenOnUnsterilizedFromJson() GpsMessage::jsonUnserialize('{]'); } + + public function testGetAttributes() + { + $message = new GpsMessage('the body', [], [], ['key1' => 'value1']); + + $attributes = $message->getAttributes(); + + $this->assertSame(['key1' => 'value1'], $attributes); + } } diff --git a/pkg/gps/Tests/GpsProducerTest.php b/pkg/gps/Tests/GpsProducerTest.php index 1e1bfae41..34dc2504f 100644 --- a/pkg/gps/Tests/GpsProducerTest.php +++ b/pkg/gps/Tests/GpsProducerTest.php @@ -33,7 +33,39 @@ public function testShouldSendMessage() $gtopic ->expects($this->once()) ->method('publish') - ->with($this->identicalTo(['data' => '{"body":"","properties":[],"headers":[]}'])) + ->with($this->identicalTo([ + 'data' => '{"body":"","properties":[],"headers":[],"attributes":[]}', + ])); + + $client = $this->createPubSubClientMock(); + $client + ->expects($this->once()) + ->method('topic') + ->with('topic-name') + ->willReturn($gtopic) + ; + + $context = $this->createContextMock(); + $context + ->expects($this->once()) + ->method('getClient') + ->willReturn($client) + ; + + $producer = new GpsProducer($context); + $producer->send($topic, $message); + } + + public function testShouldSendMessageWithAttributes() + { + $topic = new GpsTopic('topic-name'); + $message = new GpsMessage('', [], [], ['key1' => 'value1']); + + $gtopic = $this->createGTopicMock(); + $gtopic + ->expects($this->once()) + ->method('publish') + ->with($this->identicalTo(['data' => '{"body":"","properties":[],"headers":[],"attributes":{"key1":"value1"}}', 'attributes' => ['key1' => 'value1']])) ; $client = $this->createPubSubClientMock(); diff --git a/pkg/sns/composer.json b/pkg/sns/composer.json index 297fac858..3bf50bdaf 100644 --- a/pkg/sns/composer.json +++ b/pkg/sns/composer.json @@ -9,7 +9,7 @@ "php": "^7.4|^8.0", "queue-interop/queue-interop": "^0.8", "enqueue/dsn": "^0.10", - "aws/aws-sdk-php": "~3.155" + "aws/aws-sdk-php": "^3.290" }, "require-dev": { "phpunit/phpunit": "^9.5", diff --git a/pkg/snsqs/Tests/Spec/SnsQsSendToTopicAndReceiveNoWaitFromQueueTest.php b/pkg/snsqs/Tests/Spec/SnsQsSendToTopicAndReceiveNoWaitFromQueueTest.php index e370c1f32..433fcf3a7 100644 --- a/pkg/snsqs/Tests/Spec/SnsQsSendToTopicAndReceiveNoWaitFromQueueTest.php +++ b/pkg/snsqs/Tests/Spec/SnsQsSendToTopicAndReceiveNoWaitFromQueueTest.php @@ -8,6 +8,7 @@ /** * @group functional + * * @retry 5 */ class SnsQsSendToTopicAndReceiveNoWaitFromQueueTest extends SendToTopicAndReceiveNoWaitFromQueueSpec diff --git a/pkg/sqs/composer.json b/pkg/sqs/composer.json index d48b89015..cd50faf29 100644 --- a/pkg/sqs/composer.json +++ b/pkg/sqs/composer.json @@ -9,7 +9,7 @@ "php": "^7.4|^8.0", "queue-interop/queue-interop": "^0.8", "enqueue/dsn": "^0.10", - "aws/aws-sdk-php": "~3.155" + "aws/aws-sdk-php": "^3.290" }, "require-dev": { "phpunit/phpunit": "^9.5",