diff --git a/composer.json b/composer.json index d4aa772c4..b454f84fd 100644 --- a/composer.json +++ b/composer.json @@ -130,6 +130,9 @@ "ext-mongo": "1.6.14", "ext-sockets": "1" }, - "prefer-stable": true + "prefer-stable": true, + "allow-plugins": { + "php-http/discovery": false + } } } diff --git a/pkg/sns/SnsClient.php b/pkg/sns/SnsClient.php index 2d33faf25..91bce56eb 100644 --- a/pkg/sns/SnsClient.php +++ b/pkg/sns/SnsClient.php @@ -60,6 +60,11 @@ public function unsubscribe(array $args): Result return $this->callApi('unsubscribe', $args); } + public function setSubscriptionAttributes(array $args): Result + { + return $this->callApi('setSubscriptionAttributes', $args); + } + public function listSubscriptionsByTopic(array $args): Result { return $this->callApi('ListSubscriptionsByTopic', $args); @@ -135,11 +140,6 @@ private function resolveClient(): void } } - throw new \LogicException(sprintf( - 'The input client must be an instance of "%s" or "%s" or a callable that returns one of those. Got "%s"', - AwsSnsClient::class, - MultiRegionClient::class, - is_object($client) ? get_class($client) : gettype($client) - )); + throw new \LogicException(sprintf('The input client must be an instance of "%s" or "%s" or a callable that returns one of those. Got "%s"', AwsSnsClient::class, MultiRegionClient::class, is_object($client) ? get_class($client) : gettype($client))); } } diff --git a/pkg/sns/SnsContext.php b/pkg/sns/SnsContext.php index a2de3f949..2e19164d9 100644 --- a/pkg/sns/SnsContext.php +++ b/pkg/sns/SnsContext.php @@ -145,6 +145,16 @@ public function getSubscriptions(SnsDestination $destination): array return $subscriptions; } + public function setSubscriptionAttributes(SnsSubscribe $subscribe): void + { + foreach ($this->getSubscriptions($subscribe->getTopic()) as $subscription) { + $this->client->setSubscriptionAttributes(array_merge( + $subscribe->getAttributes(), + ['SubscriptionArn' => $subscription['SubscriptionArn']], + )); + } + } + public function getTopicArn(SnsDestination $destination): string { if (false == array_key_exists($destination->getTopicName(), $this->topicArns)) { diff --git a/pkg/sns/Tests/Spec/SnsContextTest.php b/pkg/sns/Tests/Spec/SnsContextTest.php index 6713abad0..9592d403f 100644 --- a/pkg/sns/Tests/Spec/SnsContextTest.php +++ b/pkg/sns/Tests/Spec/SnsContextTest.php @@ -2,13 +2,16 @@ namespace Enqueue\Sns\Tests\Spec; +use Aws\Result; use Enqueue\Sns\SnsClient; use Enqueue\Sns\SnsContext; +use Enqueue\Sns\SnsDestination; +use Enqueue\Sns\SnsSubscribe; use Interop\Queue\Spec\ContextSpec; class SnsContextTest extends ContextSpec { - public function testShouldCreateConsumerOnCreateConsumerMethodCall() + public function testShouldCreateConsumerOnCreateConsumerMethodCall(): void { $this->expectException(\LogicException::class); $this->expectExceptionMessage('SNS transport does not support consumption. You should consider using SQS instead.'); @@ -16,6 +19,32 @@ public function testShouldCreateConsumerOnCreateConsumerMethodCall() parent::testShouldCreateConsumerOnCreateConsumerMethodCall(); } + public function testSetsSubscriptionAttributes(): void + { + $client = $this->createMock(SnsClient::class); + $client->expects($this->once()) + ->method('listSubscriptionsByTopic') + ->willReturn(new Result(['Subscriptions' => [ + ['SubscriptionArn' => 'arn1'], + ['SubscriptionArn' => 'arn2'], + ]])); + $client->expects($this->exactly(2)) + ->method('setSubscriptionAttributes') + ->withConsecutive( + [$this->equalTo(['attr1' => 'value1', 'SubscriptionArn' => 'arn1'])], + [$this->equalTo(['attr1' => 'value1', 'SubscriptionArn' => 'arn2'])], + ); + + $context = new SnsContext($client, ['topic_arns' => ['topic1' => 'topicArn1']]); + $context->setSubscriptionAttributes(new SnsSubscribe( + new SnsDestination('topic1'), + 'endpoint1', + 'protocol1', + false, + ['attr1' => 'value1'], + )); + } + protected function createContext() { $client = $this->createMock(SnsClient::class); diff --git a/pkg/snsqs/SnsQsContext.php b/pkg/snsqs/SnsQsContext.php index 14dbc5acd..4a7121681 100644 --- a/pkg/snsqs/SnsQsContext.php +++ b/pkg/snsqs/SnsQsContext.php @@ -173,6 +173,17 @@ public function close(): void $this->getSqsContext()->close(); } + public function setSubscriptionAttributes(SnsQsTopic $topic, SnsQsQueue $queue, array $attributes): void + { + $this->getSnsContext()->setSubscriptionAttributes(new SnsSubscribe( + $topic, + $this->getSqsContext()->getQueueArn($queue), + SnsSubscribe::PROTOCOL_SQS, + false, + $attributes, + )); + } + private function getSnsContext(): SnsContext { if (null === $this->snsContext) { diff --git a/pkg/snsqs/Tests/Spec/SnsQsContextTest.php b/pkg/snsqs/Tests/Spec/SnsQsContextTest.php index 8554fcde6..c4fc61960 100644 --- a/pkg/snsqs/Tests/Spec/SnsQsContextTest.php +++ b/pkg/snsqs/Tests/Spec/SnsQsContextTest.php @@ -3,13 +3,47 @@ namespace Enqueue\SnsQs\Tests\Spec; use Enqueue\Sns\SnsContext; +use Enqueue\Sns\SnsSubscribe; use Enqueue\SnsQs\SnsQsContext; +use Enqueue\SnsQs\SnsQsQueue; +use Enqueue\SnsQs\SnsQsTopic; use Enqueue\Sqs\SqsConsumer; use Enqueue\Sqs\SqsContext; use Interop\Queue\Spec\ContextSpec; class SnsQsContextTest extends ContextSpec { + public function testSetsSubscriptionAttributes(): void + { + $topic = new SnsQsTopic('topic1'); + + $snsContext = $this->createMock(SnsContext::class); + $snsContext->expects($this->once()) + ->method('setSubscriptionAttributes') + ->with($this->equalTo(new SnsSubscribe( + $topic, + 'queueArn1', + 'sqs', + false, + ['attr1' => 'value1'], + ))); + + $sqsContext = $this->createMock(SqsContext::class); + $sqsContext->expects($this->any()) + ->method('createConsumer') + ->willReturn($this->createMock(SqsConsumer::class)); + $sqsContext->expects($this->any()) + ->method('getQueueArn') + ->willReturn('queueArn1'); + + $context = new SnsQsContext($snsContext, $sqsContext); + $context->setSubscriptionAttributes( + $topic, + new SnsQsQueue('queue1'), + ['attr1' => 'value1'], + ); + } + protected function createContext() { $sqsContext = $this->createMock(SqsContext::class);