Skip to content

Commit 9e81700

Browse files
authored
Merge pull request #80 from php-enqueue/amqp-dsn
[amqp] Configure by string DSN.
2 parents fda8d09 + 875f1ba commit 9e81700

23 files changed

+572
-237
lines changed

docker-compose.yml

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ services:
1010
volumes:
1111
- './:/mqdev'
1212
environment:
13+
- AMQP_DSN=amqp://rabbitmq
1314
- SYMFONY__RABBITMQ__HOST=rabbitmq
1415
- SYMFONY__RABBITMQ__USER=guest
1516
- SYMFONY__RABBITMQ__PASSWORD=guest

docs/bundle/config_reference.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ enqueue:
4343
# Port on the host.
4444
port: 5672
4545

46-
# The login name to use. Note: Max 128 characters.
47-
login: guest
46+
# The user name to use. Note: Max 128 characters.
47+
user: guest
4848

4949
# Password. Note: Max 128 characters.
50-
password: guest
50+
pass: guest
5151

5252
# The virtual host on the host. Note: Max 128 characters.
5353
vhost: /
@@ -70,11 +70,11 @@ enqueue:
7070
# Port on the host.
7171
port: 5672
7272

73-
# The login name to use. Note: Max 128 characters.
74-
login: guest
73+
# The user name to use. Note: Max 128 characters.
74+
user: guest
7575

7676
# Password. Note: Max 128 characters.
77-
password: guest
77+
pass: guest
7878

7979
# The virtual host on the host. Note: Max 128 characters.
8080
vhost: /

docs/bundle/quick_tour.md

+1-6
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,7 @@ First, you have to configure a transport layer and set one to be default.
4646
enqueue:
4747
transport:
4848
default: 'amqp'
49-
amqp:
50-
host: 'localhost'
51-
port: 5672
52-
login: 'guest'
53-
password: 'guest'
54-
vhost: '/'
49+
amqp: "amqp://"
5550
client: ~
5651
```
5752

docs/client/quick_tour.md

+1-7
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,7 @@ include __DIR__.'/vendor/autoload.php';
2525
$client = new SimpleClient([
2626
'transport' => [
2727
'default' => 'amqp',
28-
'amqp' => [
29-
'host' => 'localhost',
30-
'port' => 5672,
31-
'vhost' => '/',
32-
'login' => 'guest',
33-
'password' => 'guest',
34-
],
28+
'amqp' => 'amqp://'
3529
],
3630
'client' => [
3731
'app_name' => 'plain_php',

docs/quick_tour.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,8 @@ $client = new SimpleClient([
177177
'host' => 'localhost',
178178
'port' => 5672,
179179
'vhost' => '/',
180-
'login' => 'guest',
181-
'password' => 'guest',
180+
'user' => 'guest',
181+
'pass' => 'guest',
182182
],
183183
],
184184
'client' => true,

docs/transport/amqp.md

+17-4
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,28 @@ $ composer require enqueue/amqp-ext
2525
<?php
2626
use Enqueue\AmqpExt\AmqpConnectionFactory;
2727

28+
// connects to localhost
29+
$connectionFactory = new AmqpConnectionFactory();
30+
31+
// same as above
32+
$connectionFactory = new AmqpConnectionFactory('amqp://');
33+
34+
// same as above
35+
$connectionFactory = new AmqpConnectionFactory([]);
36+
37+
// connect to AMQP broker at example.com
2838
$connectionFactory = new AmqpConnectionFactory([
29-
'host' => '127.0.0.1',
30-
'port' => 5672,
39+
'host' => 'example.com',
40+
'port' => 1000,
3141
'vhost' => '/',
32-
'login' => 'guest',
33-
'password' => 'guest',
42+
'user' => 'user',
43+
'pass' => 'pass',
3444
'persisted' => false,
3545
]);
3646

47+
// same as above but given as DSN string
48+
$connectionFactory = new AmqpConnectionFactory('amqp://user:pass@example.com:10000/%2f');
49+
3750
$psrContext = $connectionFactory->createContext();
3851
```
3952

pkg/amqp-ext/AmqpConnectionFactory.php

+96-21
Original file line numberDiff line numberDiff line change
@@ -17,35 +17,39 @@ class AmqpConnectionFactory implements PsrConnectionFactory
1717
private $connection;
1818

1919
/**
20-
* $config = [
20+
* The config could be an array, string DSN or null. In case of null it will attempt to connect to localhost with default credentials.
21+
*
22+
* [
2123
* 'host' => amqp.host The host to connect too. Note: Max 1024 characters.
2224
* 'port' => amqp.port Port on the host.
2325
* 'vhost' => amqp.vhost The virtual host on the host. Note: Max 128 characters.
24-
* 'login' => amqp.login The login name to use. Note: Max 128 characters.
25-
* 'password' => amqp.password Password. Note: Max 128 characters.
26+
* 'user' => amqp.user The user name to use. Note: Max 128 characters.
27+
* 'pass' => amqp.password Password. Note: Max 128 characters.
2628
* 'read_timeout' => Timeout in for income activity. Note: 0 or greater seconds. May be fractional.
2729
* 'write_timeout' => Timeout in for outcome activity. Note: 0 or greater seconds. May be fractional.
2830
* 'connect_timeout' => Connection timeout. Note: 0 or greater seconds. May be fractional.
2931
* 'persisted' => bool, Whether it use single persisted connection or open a new one for every context
3032
* 'lazy' => the connection will be performed as later as possible, if the option set to true
31-
* ].
33+
* ]
34+
*
35+
* or
36+
*
37+
* amqp://user:pass@host:10000/vhost?lazy=true&persisted=false&read_timeout=2
3238
*
33-
* @param $config
39+
* @param array|string $config
3440
*/
35-
public function __construct(array $config)
41+
public function __construct($config = 'amqp://')
3642
{
37-
$this->config = array_replace([
38-
'host' => null,
39-
'port' => null,
40-
'vhost' => null,
41-
'login' => null,
42-
'password' => null,
43-
'read_timeout' => null,
44-
'write_timeout' => null,
45-
'connect_timeout' => null,
46-
'persisted' => false,
47-
'lazy' => true,
48-
], $config);
43+
if (empty($config)) {
44+
$config = [];
45+
} elseif (is_string($config)) {
46+
$config = $this->parseDsn($config);
47+
} elseif (is_array($config)) {
48+
} else {
49+
throw new \LogicException('The config must be eaither an array of options, a DSN string or null');
50+
}
51+
52+
$this->config = array_replace($this->defaultConfig(), $config);
4953
}
5054

5155
/**
@@ -64,18 +68,89 @@ public function createContext()
6468
return new AmqpContext(new \AMQPChannel($this->establishConnection()));
6569
}
6670

71+
/**
72+
* @return \AMQPConnection
73+
*/
6774
private function establishConnection()
6875
{
6976
if (false == $this->connection) {
70-
$this->connection = new \AMQPConnection($this->config);
71-
77+
$config = $this->config;
78+
$config['login'] = $this->config['user'];
79+
$config['password'] = $this->config['pass'];
80+
$this->connection = new \AMQPConnection($config);
7281
$this->config['persisted'] ? $this->connection->pconnect() : $this->connection->connect();
7382
}
74-
7583
if (false == $this->connection->isConnected()) {
7684
$this->config['persisted'] ? $this->connection->preconnect() : $this->connection->reconnect();
7785
}
7886

7987
return $this->connection;
8088
}
89+
90+
/**
91+
* @param string $dsn
92+
*
93+
* @return array
94+
*/
95+
private function parseDsn($dsn)
96+
{
97+
if ('amqp://' == $dsn) {
98+
return [];
99+
}
100+
101+
$dsnConfig = parse_url($dsn);
102+
if (false === $dsnConfig) {
103+
throw new \LogicException(sprintf('Failed to parse DSN "%s"', $dsn));
104+
}
105+
106+
$dsnConfig = array_replace([
107+
'scheme' => null,
108+
'host' => null,
109+
'port' => null,
110+
'user' => null,
111+
'pass' => null,
112+
'path' => null,
113+
'query' => null,
114+
], $dsnConfig);
115+
116+
if ('amqp' !== $dsnConfig['scheme']) {
117+
throw new \LogicException('The given DSN scheme "%s" is not supported. Could be "amqp" only.');
118+
}
119+
120+
if ($dsnConfig['query']) {
121+
$query = [];
122+
parse_str($dsnConfig['query'], $query);
123+
$dsnConfig = array_replace($query, $dsnConfig);
124+
}
125+
126+
$dsnConfig['vhost'] = ltrim($dsnConfig['path'], '/');
127+
128+
unset($dsnConfig['scheme'], $dsnConfig['query'], $dsnConfig['fragment'], $dsnConfig['path']);
129+
130+
$config = array_replace($this->defaultConfig(), $dsnConfig);
131+
$config = array_map(function ($value) {
132+
return urldecode($value);
133+
}, $config);
134+
135+
return $config;
136+
}
137+
138+
/**
139+
* @return array
140+
*/
141+
private function defaultConfig()
142+
{
143+
return [
144+
'host' => 'localhost',
145+
'port' => 5672,
146+
'vhost' => '/',
147+
'user' => 'guest',
148+
'pass' => 'guest',
149+
'read_timeout' => null,
150+
'write_timeout' => null,
151+
'connect_timeout' => null,
152+
'persisted' => false,
153+
'lazy' => true,
154+
];
155+
}
81156
}

pkg/amqp-ext/Symfony/AmqpTransportFactory.php

+13-4
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,16 @@ public function __construct($name = 'amqp')
3232
public function addConfiguration(ArrayNodeDefinition $builder)
3333
{
3434
$builder
35+
->beforeNormalization()
36+
->ifString()
37+
->then(function ($v) {
38+
return ['dsn' => $v];
39+
})
40+
->end()
3541
->children()
42+
->scalarNode('dsn')
43+
->info('The connection to AMQP broker set as a string. Other parameters are ignored if set')
44+
->end()
3645
->scalarNode('host')
3746
->defaultValue('localhost')
3847
->cannotBeEmpty()
@@ -43,12 +52,12 @@ public function addConfiguration(ArrayNodeDefinition $builder)
4352
->cannotBeEmpty()
4453
->info('Port on the host.')
4554
->end()
46-
->scalarNode('login')
55+
->scalarNode('user')
4756
->defaultValue('guest')
4857
->cannotBeEmpty()
49-
->info('The login name to use. Note: Max 128 characters.')
58+
->info('The user name to use. Note: Max 128 characters.')
5059
->end()
51-
->scalarNode('password')
60+
->scalarNode('pass')
5261
->defaultValue('guest')
5362
->cannotBeEmpty()
5463
->info('Password. Note: Max 128 characters.')
@@ -85,7 +94,7 @@ public function addConfiguration(ArrayNodeDefinition $builder)
8594
public function createConnectionFactory(ContainerBuilder $container, array $config)
8695
{
8796
$factory = new Definition(AmqpConnectionFactory::class);
88-
$factory->setArguments([$config]);
97+
$factory->setArguments(isset($config['dsn']) ? [$config['dsn']] : [$config]);
8998

9099
$factoryId = sprintf('enqueue.transport.%s.connection_factory', $this->getName());
91100
$container->setDefinition($factoryId, $factory);

0 commit comments

Comments
 (0)