Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit bf7f60c

Browse files
committed
[Messenger] Add SQS transport
1 parent 5b38f70 commit bf7f60c

22 files changed

+1314
-0
lines changed

.travis.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ env:
2121
- SYMFONY_PROCESS_PHP_TEST_BINARY=~/.phpenv/shims/php
2222
- MESSENGER_AMQP_DSN=amqp://localhost/%2f/messages
2323
- MESSENGER_REDIS_DSN=redis://127.0.0.1:7006/messages
24+
- MESSENGER_SQS_DSN=sqs://localhost:9494/messages?sslmode=disable
2425
- SYMFONY_PHPUNIT_DISABLE_RESULT_CACHE=1
2526

2627
matrix:
@@ -62,6 +63,11 @@ before_install:
6263
docker run -d -p 7000:7000 -p 7001:7001 -p 7002:7002 -p 7003:7003 -p 7004:7004 -p 7005:7005 -p 7006:7006 -p 7007:7007 -e "STANDALONE=true" --name redis-cluster grokzen/redis-cluster:5.0.4
6364
export REDIS_CLUSTER_HOSTS='localhost:7000 localhost:7001 localhost:7002 localhost:7003 localhost:7004 localhost:7005'
6465
66+
- |
67+
# Start Sqs server
68+
docker pull feathj/fake-sqs
69+
docker run -d -p 9494:9494 --name sqs feathj/fake-sqs
70+
6571
- |
6672
# General configuration
6773
set -e

src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@
8585
<tag name="kernel.reset" method="reset" />
8686
</service>
8787

88+
<service id="messenger.transport.sqs.factory" class="Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\AmazonSqsTransportFactory">
89+
<tag name="messenger.transport_factory" />
90+
</service>
91+
8892
<!-- retry -->
8993
<service id="messenger.retry_strategy_locator">
9094
<tag name="container.service_locator" />
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/Tests export-ignore
2+
/phpunit.xml.dist export-ignore
3+
/.gitignore export-ignore
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
vendor/
2+
composer.lock
3+
phpunit.xml
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CHANGELOG
2+
=========
3+
4+
5.1.0
5+
-----
6+
7+
* Introduced the Amazon SQS bridge.
8+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2020 Fabien Potencier
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is furnished
8+
to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
THE SOFTWARE.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Amazon SQS Messenger
2+
====================
3+
4+
Provides Amazon SQS integration for Symfony Messenger.
5+
6+
Resources
7+
---------
8+
9+
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
10+
* [Report issues](https://github.com/symfony/symfony/issues) and
11+
[send Pull Requests](https://github.com/symfony/symfony/pulls)
12+
in the [main Symfony repository](https://github.com/symfony/symfony)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Symfony\Component\Messenger\Bridge\AmazonSqs\Tests\Fixtures;
4+
5+
class DummyMessage
6+
{
7+
private $message;
8+
9+
public function __construct(string $message)
10+
{
11+
$this->message = $message;
12+
}
13+
14+
public function getMessage(): string
15+
{
16+
return $this->message;
17+
}
18+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Messenger\Bridge\AmazonSqs\Tests\Transport;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Messenger\Bridge\AmazonSqs\Tests\Fixtures\DummyMessage;
16+
use Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\Connection;
17+
18+
class AmazonSqsIntegrationTest extends TestCase
19+
{
20+
private $connection;
21+
22+
protected function setUp(): void
23+
{
24+
if (!getenv('MESSENGER_SQS_DSN')) {
25+
$this->markTestSkipped('The "MESSENGER_SQS_DSN" environment variable is required.');
26+
}
27+
28+
$this->connection = Connection::fromDsn(getenv('MESSENGER_SQS_DSN'), []);
29+
$this->connection->setup();
30+
$this->clearSqs();
31+
}
32+
33+
public function testConnectionSendAndGet()
34+
{
35+
$this->connection->send('{"message": "Hi"}', ['type' => DummyMessage::class]);
36+
$this->assertSame(1, $this->connection->getMessageCount());
37+
38+
$wait = 0;
39+
while ((null === $encoded = $this->connection->get()) && $wait++ < 200) {
40+
usleep(5000);
41+
}
42+
43+
$this->assertEquals('{"message": "Hi"}', $encoded['body']);
44+
$this->assertEquals(['type' => DummyMessage::class], $encoded['headers']);
45+
}
46+
47+
private function clearSqs()
48+
{
49+
$wait = 0;
50+
while ($wait++ < 50) {
51+
if (null === $message = $this->connection->get()) {
52+
usleep(5000);
53+
continue;
54+
}
55+
$this->connection->delete($message['id']);
56+
}
57+
}
58+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Messenger\Bridge\AmazonSqs\Tests\Transport;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Messenger\Bridge\AmazonSqs\Tests\Fixtures\DummyMessage;
16+
use Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\AmazonSqsReceiver;
17+
use Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\Connection;
18+
use Symfony\Component\Messenger\Exception\MessageDecodingFailedException;
19+
use Symfony\Component\Messenger\Transport\Serialization\PhpSerializer;
20+
use Symfony\Component\Messenger\Transport\Serialization\Serializer;
21+
use Symfony\Component\Serializer as SerializerComponent;
22+
use Symfony\Component\Serializer\Encoder\JsonEncoder;
23+
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
24+
25+
class AmazonSqsReceiverTest extends TestCase
26+
{
27+
public function testItReturnsTheDecodedMessageToTheHandler()
28+
{
29+
$serializer = $this->createSerializer();
30+
31+
$sqsEnvelop = $this->createSqsEnvelope();
32+
$connection = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock();
33+
$connection->method('get')->willReturn($sqsEnvelop);
34+
35+
$receiver = new AmazonSqsReceiver($connection, $serializer);
36+
$actualEnvelopes = iterator_to_array($receiver->get());
37+
$this->assertCount(1, $actualEnvelopes);
38+
$this->assertEquals(new DummyMessage('Hi'), $actualEnvelopes[0]->getMessage());
39+
}
40+
41+
public function testItRejectTheMessageIfThereIsAMessageDecodingFailedException()
42+
{
43+
$this->expectException(MessageDecodingFailedException::class);
44+
45+
$serializer = $this->createMock(PhpSerializer::class);
46+
$serializer->method('decode')->willThrowException(new MessageDecodingFailedException());
47+
48+
$sqsEnvelop = $this->createSqsEnvelope();
49+
$connection = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock();
50+
$connection->method('get')->willReturn($sqsEnvelop);
51+
$connection->expects($this->once())->method('delete');
52+
53+
$receiver = new AmazonSqsReceiver($connection, $serializer);
54+
iterator_to_array($receiver->get());
55+
}
56+
57+
private function createSqsEnvelope()
58+
{
59+
return [
60+
'id' => 1,
61+
'body' => '{"message": "Hi"}',
62+
'headers' => [
63+
'type' => DummyMessage::class,
64+
],
65+
];
66+
}
67+
68+
private function createSerializer(): Serializer
69+
{
70+
$serializer = new Serializer(
71+
new SerializerComponent\Serializer([new ObjectNormalizer()], ['json' => new JsonEncoder()])
72+
);
73+
74+
return $serializer;
75+
}
76+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Messenger\Bridge\AmazonSqs\Tests\Transport;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Messenger\Bridge\AmazonSqs\Tests\Fixtures\DummyMessage;
16+
use Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\AmazonSqsSender;
17+
use Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\Connection;
18+
use Symfony\Component\Messenger\Envelope;
19+
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
20+
21+
class AmazonSqsSenderTest extends TestCase
22+
{
23+
public function testSend()
24+
{
25+
$envelope = new Envelope(new DummyMessage('Oy'));
26+
$encoded = ['body' => '...', 'headers' => ['type' => DummyMessage::class]];
27+
28+
$connection = $this->getMockBuilder(Connection::class)
29+
->disableOriginalConstructor()
30+
->getMock();
31+
$connection->expects($this->once())->method('send')->with($encoded['body'], $encoded['headers']);
32+
33+
$serializer = $this->getMockBuilder(SerializerInterface::class)->getMock();
34+
$serializer->method('encode')->with($envelope)->willReturnOnConsecutiveCalls($encoded);
35+
36+
$sender = new AmazonSqsSender($connection, $serializer);
37+
$sender->send($envelope);
38+
}
39+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Messenger\Bridge\AmazonSqs\Tests\Transport;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\AmazonSqsTransportFactory;
16+
17+
class AmazonSqsTransportFactoryTest extends TestCase
18+
{
19+
public function testSupportsOnlySqsTransports()
20+
{
21+
$factory = new AmazonSqsTransportFactory();
22+
23+
$this->assertTrue($factory->supports('sqs://localhost', []));
24+
$this->assertFalse($factory->supports('redis://localhost', []));
25+
$this->assertFalse($factory->supports('invalid-dsn', []));
26+
}
27+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Messenger\Bridge\AmazonSqs\Tests\Transport;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Messenger\Bridge\AmazonSqs\Tests\Fixtures\DummyMessage;
16+
use Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\AmazonSqsTransport;
17+
use Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\Connection;
18+
use Symfony\Component\Messenger\Envelope;
19+
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
20+
use Symfony\Component\Messenger\Transport\TransportInterface;
21+
22+
class AmazonSqsTransportTest extends TestCase
23+
{
24+
public function testItIsATransport()
25+
{
26+
$transport = $this->getTransport();
27+
28+
$this->assertInstanceOf(TransportInterface::class, $transport);
29+
}
30+
31+
public function testReceivesMessages()
32+
{
33+
$transport = $this->getTransport(
34+
$serializer = $this->getMockBuilder(SerializerInterface::class)->getMock(),
35+
$connection = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock()
36+
);
37+
38+
$decodedMessage = new DummyMessage('Decoded.');
39+
40+
$sqsEnvelope = [
41+
'id' => '5',
42+
'body' => 'body',
43+
'headers' => ['my' => 'header'],
44+
];
45+
46+
$serializer->method('decode')->with(['body' => 'body', 'headers' => ['my' => 'header']])->willReturn(new Envelope($decodedMessage));
47+
$connection->method('get')->willReturn($sqsEnvelope);
48+
49+
$envelopes = iterator_to_array($transport->get());
50+
$this->assertSame($decodedMessage, $envelopes[0]->getMessage());
51+
}
52+
53+
private function getTransport(SerializerInterface $serializer = null, Connection $connection = null)
54+
{
55+
$serializer = $serializer ?: $this->getMockBuilder(SerializerInterface::class)->getMock();
56+
$connection = $connection ?: $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock();
57+
58+
return new AmazonSqsTransport($connection, $serializer);
59+
}
60+
}

0 commit comments

Comments
 (0)