Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
"datadog/php-datadogstatsd": "^1.3"
},
"require-dev": {
"async-aws/sns": "^0.5.0",
"async-aws/sqs": "^1.0.0",
"phpunit/phpunit": "^7.5",
"phpstan/phpstan": "^0.12",
"queue-interop/queue-spec": "^0.6",
Expand Down
2 changes: 1 addition & 1 deletion docs/transport/sqs.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ $factory = new SqsConnectionFactory('sqs:?key=aKey&secret=aSecret&region=aRegion
$context = $factory->createContext();

// using a pre-configured client
$client = new Aws\Sqs\SqsClient([ /* ... */ ]);
$client = new AsyncAws\Sqs\SqsClient([ /* ... */ ]);
$factory = new SqsConnectionFactory($client);

// if you have enqueue/enqueue library installed you can use a factory to build context from DSN
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,13 @@ services:

test.sqs_client:
public: true
class: 'Aws\Sqs\SqsClient'
class: 'AsyncAws\Sqs\SqsClient'
arguments:
-
endpoint: '%env(AWS_SQS_ENDPOINT)%'
region: '%env(AWS_SQS_REGION)%'
version: '%env(AWS_SQS_VERSION)%'
credentials:
key: '%env(AWS_SQS_KEY)%'
secret: '%env(AWS_SQS_SECRET)%'
accessKeyId: '%env(AWS_SQS_KEY)%'
accessKeySecret: '%env(AWS_SQS_SECRET)%'

test.sqs_custom_connection_factory_factory:
class: 'Enqueue\Bundle\Tests\Functional\App\SqsCustomConnectionFactoryFactory'
Expand Down
56 changes: 56 additions & 0 deletions pkg/sns/SnsAsyncClient.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

declare(strict_types=1);

namespace Enqueue\Sns;

use AsyncAws\Sns\Result\CreateTopicResponse;
use AsyncAws\Sns\Result\ListSubscriptionsByTopicResponse;
use AsyncAws\Sns\Result\PublishResponse;
use AsyncAws\Sns\Result\SubscribeResponse;
use AsyncAws\Sns\SnsClient as AwsSnsClient;

/**
* @internal
*/
class SnsAsyncClient
{
private $client;

public function __construct(AwsSnsClient $client)
{
$this->client = $client;
}

public function createTopic(array $args): CreateTopicResponse
{
return $this->client->CreateTopic($args);
}

public function deleteTopic(string $topicArn): void
{
$this->client->DeleteTopic([
'TopicArn' => $topicArn,
]);
}

public function publish(array $args): PublishResponse
{
return $this->client->Publish($args);
}

public function subscribe(array $args): SubscribeResponse
{
return $this->client->Subscribe($args);
}

public function unsubscribe(array $args): void
{
$this->client->Unsubscribe($args);
}

public function listSubscriptionsByTopic(array $args): ListSubscriptionsByTopicResponse
{
return $this->client->ListSubscriptionsByTopic($args);
}
}
2 changes: 2 additions & 0 deletions pkg/sns/SnsClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
use Aws\Result;
use Aws\Sns\SnsClient as AwsSnsClient;

@trigger_error(sprintf('The class "%s" is deprecated since 0.10. Use "%s" instead.', __CLASS__, SnsAsyncClient::class), E_USER_DEPRECATED);

class SnsClient
{
/**
Expand Down
59 changes: 28 additions & 31 deletions pkg/sns/SnsConnectionFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Enqueue\Sns;

use Aws\Sdk;
use AsyncAws\Sns\SnsClient as AsyncAwsSnsClient;
use Aws\Sns\SnsClient as AwsSnsClient;
use Enqueue\Dsn\Dsn;
use Interop\Queue\ConnectionFactory;
Expand All @@ -18,7 +18,7 @@ class SnsConnectionFactory implements ConnectionFactory
private $config;

/**
* @var SnsClient
* @var SnsClient|SnsAsyncClient
*/
private $client;

Expand All @@ -28,20 +28,25 @@ class SnsConnectionFactory implements ConnectionFactory
* 'secret' => null, AWS credentials. If no credentials are provided, the SDK will attempt to load them from the environment.
* 'token' => null, AWS credentials. If no credentials are provided, the SDK will attempt to load them from the environment.
* 'region' => null, (string, required) Region to connect to. See http://docs.aws.amazon.com/general/latest/gr/rande.html for a list of available regions.
* 'version' => '2012-11-05', (string, required) The version of the webservice to utilize
* 'lazy' => true, Enable lazy connection (boolean)
* 'endpoint' => null (string, default=null) The full URI of the webservice. This is only required when connecting to a custom endpoint e.g. localstack
* 'profile' => null, (string, default=null) The name of an AWS profile to used, if provided the SDK will attempt to read associated credentials from the ~/.aws/credentials file.
* ].
*
* or
*
* sns:
* sns::?key=aKey&secret=aSecret&token=aToken
*
* @param array|string|SnsClient|null $config
* @param array|string|AwsSnsClient|AsyncAwsSnsClient|null $config
*/
public function __construct($config = 'sns:')
{
if ($config instanceof AsyncAwsSnsClient) {
$this->client = new SnsAsyncClient($config);
$this->config = $this->defaultConfig();

return;
}
if ($config instanceof AwsSnsClient) {
$this->client = new SnsClient($config);
$this->config = ['lazy' => false] + $this->defaultConfig();
Expand All @@ -60,7 +65,7 @@ public function __construct($config = 'sns:')
unset($config['dsn']);
}
} else {
throw new \LogicException(sprintf('The config must be either an array of options, a DSN string, null or instance of %s', AwsSnsClient::class));
throw new \LogicException(sprintf('The config must be either an array of options, a DSN string, null or instance of %s', AsyncAwsSnsClient::class));
}

$this->config = array_replace($this->defaultConfig(), $config);
Expand All @@ -74,63 +79,56 @@ public function createContext(): Context
return new SnsContext($this->establishConnection(), $this->config);
}

private function establishConnection(): SnsClient
/**
* @todo in 0.11 restore return typehint
*
* @return SnsAsyncClient|SnsClient
*/
private function establishConnection()
{
if ($this->client) {
return $this->client;
}

$config = [
'version' => $this->config['version'],
'region' => $this->config['region'],
];

if (isset($this->config['endpoint'])) {
$config['endpoint'] = $this->config['endpoint'];
}

if (isset($this->config['profile'])) {
$config['profile'] = $this->config['profile'];
}

if ($this->config['key'] && $this->config['secret']) {
$config['credentials'] = [
'key' => $this->config['key'],
'secret' => $this->config['secret'],
];
$config['accessKeyId'] = $this->config['key'];
$config['accessKeySecret'] = $this->config['secret'];

if ($this->config['token']) {
$config['credentials']['token'] = $this->config['token'];
$config['sessionToken'] = $this->config['token'];
}
}

$establishConnection = function () use ($config) {
return (new Sdk(['Sns' => $config]))->createMultiRegionSns();
};

$this->client = $this->config['lazy'] ?
new SnsClient($establishConnection) :
new SnsClient($establishConnection())
;

return $this->client;
return $this->client = new SnsAsyncClient(new AsyncAwsSnsClient($config));
}

private function parseDsn(string $dsn): array
{
$dsn = Dsn::parseFirst($dsn);

if ('sns' !== $dsn->getSchemeProtocol()) {
throw new \LogicException(sprintf(
'The given scheme protocol "%s" is not supported. It must be "sns"',
$dsn->getSchemeProtocol()
));
throw new \LogicException(sprintf('The given scheme protocol "%s" is not supported. It must be "sns"', $dsn->getSchemeProtocol()));
}

return array_filter(array_replace($dsn->getQuery(), [
'key' => $dsn->getString('key'),
'secret' => $dsn->getString('secret'),
'token' => $dsn->getString('token'),
'region' => $dsn->getString('region'),
'version' => $dsn->getString('version'),
'lazy' => $dsn->getBool('lazy'),
'endpoint' => $dsn->getString('endpoint'),
'profile' => $dsn->getString('profile'),
]), function ($value) { return null !== $value; });
}

Expand All @@ -141,9 +139,8 @@ private function defaultConfig(): array
'secret' => null,
'token' => null,
'region' => null,
'version' => '2010-03-31',
'lazy' => true,
'endpoint' => null,
'profile' => null,
];
}
}
Loading