Skip to content

Commit 2af7a2d

Browse files
committed
Amazon SNS transport.
1 parent ce8414d commit 2af7a2d

36 files changed

+1786
-5
lines changed

Diff for: composer.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
"doctrine/orm": "~2.4",
2626
"mongodb/mongodb": "^1.2",
2727
"pda/pheanstalk": "^3",
28-
"aws/aws-sdk-php": "~3.26",
28+
"aws/aws-sdk-php": "^3.26",
2929
"stomp-php/stomp-php": "^4",
3030
"php-http/guzzle6-adapter": "^1.1",
3131
"php-http/client-common": "^1.7@dev",
@@ -75,6 +75,7 @@
7575
"Enqueue\\Redis\\": "pkg/redis/",
7676
"Enqueue\\SimpleClient\\": "pkg/simple-client/",
7777
"Enqueue\\Sqs\\": "pkg/sqs/",
78+
"Enqueue\\Sns\\": "pkg/sns/",
7879
"Enqueue\\Stomp\\": "pkg/stomp/",
7980
"Enqueue\\Test\\": "pkg/test/",
8081
"Enqueue\\Dsn\\": "pkg/dsn/",

Diff for: docker-compose.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ services:
3131
- PHPREDIS_DSN=redis+phpredis://redis
3232
- GPS_DSN=gps:?projectId=mqdev&emulatorHost=http://google-pubsub:8085
3333
- SQS_DSN=sqs:?key=key&secret=secret&region=us-east-1&endpoint=http://localstack:4576&version=latest
34+
- SNS_DSN=sns:?key=key&secret=secret&region=us-east-1&endpoint=http://localstack:4575&version=latest
3435
- WAMP_DSN=wamp://thruway:9090
3536
- REDIS_HOST=redis
3637
- REDIS_PORT=6379
@@ -121,9 +122,10 @@ services:
121122
image: 'localstack/localstack:latest'
122123
ports:
123124
- '4576:4576'
125+
- '4575:4575'
124126
environment:
125127
HOSTNAME_EXTERNAL: 'localstack'
126-
SERVICES: 'sqs'
128+
SERVICES: 'sqs,sns'
127129

128130
influxdb:
129131
image: 'influxdb:latest'

Diff for: phpunit.xml.dist

+4
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@
6161
<directory>pkg/sqs/Tests</directory>
6262
</testsuite>
6363

64+
<testsuite name="sns transport">
65+
<directory>pkg/sns/Tests</directory>
66+
</testsuite>
67+
6468
<testsuite name="pheanstalk transport">
6569
<directory>pkg/pheanstalk/Tests</directory>
6670
</testsuite>

Diff for: pkg/sns/.gitattributes

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/Tests export-ignore
2+
.gitattributes export-ignore
3+
.gitignore export-ignore
4+
.travis.yml export-ignore
5+
phpunit.xml.dist export-ignore

Diff for: pkg/sns/.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
*~
2+
/composer.lock
3+
/composer.phar
4+
/phpunit.xml
5+
/vendor/
6+
/.idea/

Diff for: pkg/sns/.travis.yml

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
sudo: false
2+
3+
git:
4+
depth: 10
5+
6+
language: php
7+
8+
php:
9+
- '7.1'
10+
- '7.2'
11+
12+
cache:
13+
directories:
14+
- $HOME/.composer/cache
15+
16+
install:
17+
- composer self-update
18+
- composer install --prefer-source
19+
20+
script:
21+
- vendor/bin/phpunit --exclude-group=functional

Diff for: pkg/sns/LICENSE

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
The MIT License (MIT)
2+
Copyright (c) 2018 Max Kotliar
3+
4+
Permission is hereby granted, free of charge, to any person obtaining a copy
5+
of this software and associated documentation files (the "Software"), to deal
6+
in the Software without restriction, including without limitation the rights
7+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
copies of the Software, and to permit persons to whom the Software is furnished
9+
to do so, subject to the following conditions:
10+
11+
The above copyright notice and this permission notice shall be included in all
12+
copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+
THE SOFTWARE.

Diff for: pkg/sns/README.md

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<h2 align="center">Supporting Enqueue</h2>
2+
3+
Enqueue is an MIT-licensed open source project with its ongoing development made possible entirely by the support of community and our customers. If you'd like to join them, please consider:
4+
5+
- [Become a sponsor](https://www.patreon.com/makasim)
6+
- [Become our client](http://forma-pro.com/)
7+
8+
---
9+
10+
# Amazon SNS Transport
11+
12+
[![Gitter](https://badges.gitter.im/php-enqueue/Lobby.svg)](https://gitter.im/php-enqueue/Lobby)
13+
[![Build Status](https://travis-ci.org/php-enqueue/sns.png?branch=master)](https://travis-ci.org/php-enqueue/sns)
14+
[![Total Downloads](https://poser.pugx.org/enqueue/sns/d/total.png)](https://packagist.org/packages/enqueue/sns)
15+
[![Latest Stable Version](https://poser.pugx.org/enqueue/sns/version.png)](https://packagist.org/packages/enqueue/sns)
16+
17+
This is an implementation of Queue Interop specification. It allows you to send and consume message using [Amazon SNS](https://aws.amazon.com/sns/) service.
18+
19+
## Resources
20+
21+
* [Site](https://enqueue.forma-pro.com/)
22+
* [Documentation](https://github.com/php-enqueue/enqueue-dev/blob/master/docs/transport/sns.md)
23+
* [Questions](https://gitter.im/php-enqueue/Lobby)
24+
* [Issue Tracker](https://github.com/php-enqueue/enqueue-dev/issues)
25+
26+
## License
27+
28+
It is released under the [MIT License](LICENSE).

Diff for: pkg/sns/SnsClient.php

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Enqueue\Sns;
6+
7+
use Aws\MultiRegionClient;
8+
use Aws\Result;
9+
use Aws\Sns\SnsClient as AwsSnsClient;
10+
11+
class SnsClient
12+
{
13+
/**
14+
* @var AwsSnsClient
15+
*/
16+
private $singleClient;
17+
18+
/**
19+
* @var MultiRegionClient
20+
*/
21+
private $multiClient;
22+
23+
/**
24+
* @var callable
25+
*/
26+
private $inputClient;
27+
28+
/**
29+
* @param AwsSnsClient|MultiRegionClient|callable $inputClient
30+
*/
31+
public function __construct($inputClient)
32+
{
33+
$this->inputClient = $inputClient;
34+
}
35+
36+
public function createTopic(array $args): Result
37+
{
38+
return $this->callApi('createTopic', $args);
39+
}
40+
41+
public function publish(array $args): Result
42+
{
43+
return $this->callApi('publish', $args);
44+
}
45+
46+
public function subscribe(array $args): Result
47+
{
48+
return $this->callApi('subscribe', $args);
49+
}
50+
51+
public function getAWSClient(): AwsSnsClient
52+
{
53+
$this->resolveClient();
54+
55+
if ($this->singleClient) {
56+
return $this->singleClient;
57+
}
58+
59+
if ($this->multiClient) {
60+
$mr = new \ReflectionMethod($this->multiClient, 'getClientFromPool');
61+
$mr->setAccessible(true);
62+
$singleClient = $mr->invoke($this->multiClient, $this->multiClient->getRegion());
63+
$mr->setAccessible(false);
64+
65+
return $singleClient;
66+
}
67+
68+
throw new \LogicException('The multi or single client must be set');
69+
}
70+
71+
private function callApi(string $name, array $args): Result
72+
{
73+
$this->resolveClient();
74+
75+
if ($this->singleClient) {
76+
if (false == empty($args['@region'])) {
77+
throw new \LogicException('Cannot send message to another region because transport is configured with single aws client');
78+
}
79+
80+
unset($args['@region']);
81+
82+
return call_user_func([$this->singleClient, $name], $args);
83+
}
84+
85+
if ($this->multiClient) {
86+
return call_user_func([$this->multiClient, $name], $args);
87+
}
88+
89+
throw new \LogicException('The multi or single client must be set');
90+
}
91+
92+
private function resolveClient(): void
93+
{
94+
if ($this->singleClient || $this->multiClient) {
95+
return;
96+
}
97+
98+
$client = $this->inputClient;
99+
if ($client instanceof MultiRegionClient) {
100+
$this->multiClient = $client;
101+
102+
return;
103+
} elseif ($client instanceof AwsSnsClient) {
104+
$this->singleClient = $client;
105+
106+
return;
107+
} elseif (is_callable($client)) {
108+
$client = call_user_func($client);
109+
if ($client instanceof MultiRegionClient) {
110+
$this->multiClient = $client;
111+
112+
return;
113+
}
114+
if ($client instanceof AwsSnsClient) {
115+
$this->singleClient = $client;
116+
117+
return;
118+
}
119+
}
120+
121+
throw new \LogicException(sprintf(
122+
'The input client must be an instance of "%s" or "%s" or a callable that returns one of those. Got "%s"',
123+
AwsSnsClient::class,
124+
MultiRegionClient::class,
125+
is_object($client) ? get_class($client) : gettype($client)
126+
));
127+
}
128+
}

0 commit comments

Comments
 (0)