Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 5eeb4a9

Browse files
authoredSep 8, 2018
Merge pull request #528 from php-enqueue/redis-config-improvements
[redis] Improve redis config, use enqueue/dsn
2 parents 33801ad + f1b704d commit 5eeb4a9

11 files changed

+372
-330
lines changed
 

‎docker-compose.yml

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ services:
2121
- AMQP_DSN=amqp://guest:guest@rabbitmq:5672/mqdev
2222
- AMQPS_DSN=amqps://guest:guest@rabbitmqssl:5671
2323
- DOCTRINE_DSN=mysql://root:rootpass@mysql/mqdev
24+
- PREDIS_DSN=redis+predis://redis
25+
- PHPREDIS_DSN=redis+phpredis://redis
2426
- RABBITMQ_HOST=rabbitmq
2527
- RABBITMQ_USER=guest
2628
- RABBITMQ_PASSWORD=guest

‎pkg/redis/PRedis.php

+26-39
Original file line numberDiff line numberDiff line change
@@ -13,39 +13,42 @@ class PRedis implements Redis
1313
/**
1414
* @var array
1515
*/
16-
private $config;
16+
private $parameters;
17+
18+
/**
19+
* @var array
20+
*/
21+
private $options;
1722

1823
/**
1924
* @var ClientInterface
2025
*/
2126
private $redis;
2227

2328
/**
24-
* @param ClientInterface $redis
29+
* @see https://github.com/nrk/predis/wiki/Client-Options
2530
*/
2631
public function __construct(array $config)
2732
{
28-
$this->config = $this->config = array_replace([
29-
'scheme' => null,
30-
'host' => null,
31-
'port' => null,
32-
'pass' => null,
33-
'user' => null,
34-
'timeout' => null,
35-
'reserved' => null,
36-
'retry_interval' => null,
37-
'persisted' => false,
38-
'database' => 0,
39-
], $config);
40-
41-
// Predis client wants the key to be named "password"
42-
$this->config['password'] = $this->config['pass'];
43-
unset($this->config['pass']);
33+
$this->options = $config['predis_options'];
34+
35+
$this->parameters = [
36+
'scheme' => $config['scheme'],
37+
'host' => $config['host'],
38+
'port' => $config['port'],
39+
'password' => $config['password'],
40+
'path' => $config['path'],
41+
'async' => $config['async'],
42+
'persistent' => $config['persistent'],
43+
'timeout' => $config['timeout'],
44+
'read_write_timeout' => $config['read_write_timeout'],
45+
];
46+
47+
if ($config['ssl']) {
48+
$this->parameters['ssl'] = $config['ssl'];
49+
}
4450
}
4551

46-
/**
47-
* {@inheritdoc}
48-
*/
4952
public function lpush(string $key, string $value): int
5053
{
5154
try {
@@ -55,9 +58,6 @@ public function lpush(string $key, string $value): int
5558
}
5659
}
5760

58-
/**
59-
* {@inheritdoc}
60-
*/
6161
public function brpop(array $keys, int $timeout): ?RedisResult
6262
{
6363
try {
@@ -71,9 +71,6 @@ public function brpop(array $keys, int $timeout): ?RedisResult
7171
}
7272
}
7373

74-
/**
75-
* {@inheritdoc}
76-
*/
7774
public function rpop(string $key): ?RedisResult
7875
{
7976
try {
@@ -87,34 +84,24 @@ public function rpop(string $key): ?RedisResult
8784
}
8885
}
8986

90-
/**
91-
* {@inheritdoc}
92-
*/
9387
public function connect(): void
9488
{
9589
if ($this->redis) {
9690
return;
9791
}
9892

99-
$this->redis = new Client($this->config, ['exceptions' => true]);
93+
$this->redis = new Client($this->parameters, $this->options);
10094

101-
// No need to pass "auth" here because Predis already handles
102-
// this internally
95+
// No need to pass "auth" here because Predis already handles this internally
10396

10497
$this->redis->connect();
10598
}
10699

107-
/**
108-
* {@inheritdoc}
109-
*/
110100
public function disconnect(): void
111101
{
112102
$this->redis->disconnect();
113103
}
114104

115-
/**
116-
* {@inheritdoc}
117-
*/
118105
public function del(string $key): void
119106
{
120107
$this->redis->del([$key]);

‎pkg/redis/PhpRedis.php

+49-59
Original file line numberDiff line numberDiff line change
@@ -15,107 +15,97 @@ class PhpRedis implements Redis
1515
private $config;
1616

1717
/**
18-
* @param array $config
18+
* @see https://github.com/phpredis/phpredis#parameters
1919
*/
2020
public function __construct(array $config)
2121
{
22-
$this->config = array_replace([
23-
'scheme' => null,
24-
'host' => null,
25-
'port' => null,
26-
'pass' => null,
27-
'user' => null,
28-
'timeout' => .0,
29-
'reserved' => null,
30-
'retry_interval' => null,
31-
'persisted' => false,
32-
'database' => 0,
33-
], $config);
22+
$this->config = $config;
3423
}
3524

36-
/**
37-
* {@inheritdoc}
38-
*/
3925
public function lpush(string $key, string $value): int
4026
{
41-
return $this->redis->lPush($key, $value);
27+
try {
28+
return $this->redis->lPush($key, $value);
29+
} catch (\RedisException $e) {
30+
throw new ServerException('lpush command has failed', null, $e);
31+
}
4232
}
4333

44-
/**
45-
* {@inheritdoc}
46-
*/
4734
public function brpop(array $keys, int $timeout): ?RedisResult
4835
{
49-
if ($result = $this->redis->brPop($keys, $timeout)) {
50-
return new RedisResult($result[0], $result[1]);
36+
try {
37+
if ($result = $this->redis->brPop($keys, $timeout)) {
38+
return new RedisResult($result[0], $result[1]);
39+
}
40+
41+
return null;
42+
} catch (\RedisException $e) {
43+
throw new ServerException('brpop command has failed', null, $e);
5144
}
52-
53-
return null;
5445
}
5546

56-
/**
57-
* {@inheritdoc}
58-
*/
5947
public function rpop(string $key): ?RedisResult
6048
{
61-
if ($message = $this->redis->rPop($key)) {
62-
return new RedisResult($key, $message);
49+
try {
50+
if ($message = $this->redis->rPop($key)) {
51+
return new RedisResult($key, $message);
52+
}
53+
54+
return null;
55+
} catch (\RedisException $e) {
56+
throw new ServerException('rpop command has failed', null, $e);
6357
}
64-
65-
return null;
6658
}
6759

68-
/**
69-
* {@inheritdoc}
70-
*/
7160
public function connect(): void
7261
{
7362
if ($this->redis) {
7463
return;
7564
}
7665

77-
if ('rediss' == $this->config['scheme']) {
78-
throw new \LogicException('The phpredis extension does not support secured connections. Try to use predis library as vendor.');
66+
$supportedSchemes = ['redis', 'tcp', 'unix'];
67+
if (false == in_array($this->config['scheme'], $supportedSchemes, true)) {
68+
throw new \LogicException(sprintf(
69+
'The given scheme protocol "%s" is not supported by php extension. It must be one of "%s"',
70+
$this->config['scheme'],
71+
implode('", "', $supportedSchemes)
72+
));
7973
}
8074

8175
$this->redis = new \Redis();
8276

83-
if ($this->config['persisted']) {
84-
$this->redis->pconnect(
85-
$this->config['host'],
86-
$this->config['port'],
87-
$this->config['timeout']
88-
);
89-
} else {
90-
$this->redis->connect(
91-
$this->config['host'],
92-
$this->config['port'],
93-
$this->config['timeout'],
94-
$this->config['reserved'],
95-
$this->config['retry_interval']
96-
);
77+
$connectionMethod = $this->config['persistent'] ? 'pconnect' : 'connect';
78+
79+
$result = call_user_func(
80+
[$this->redis, $connectionMethod],
81+
'unix' === $this->config['scheme'] ? $this->config['path'] : $this->config['host'],
82+
$this->config['port'],
83+
$this->config['timeout'],
84+
$this->config['persistent'] ? ($this->config['phpredis_persistent_id'] ?? null) : null,
85+
$this->config['phpredis_retry_interval'] ?? null,
86+
$this->config['read_write_timeout']
87+
);
88+
89+
if (false == $result) {
90+
throw new ServerException('Failed to connect.');
9791
}
9892

99-
if ($this->config['pass']) {
100-
$this->redis->auth($this->config['pass']);
93+
if ($this->config['password']) {
94+
$this->redis->auth($this->config['password']);
10195
}
10296

103-
$this->redis->select($this->config['database']);
97+
if (null !== $this->config['database']) {
98+
$this->redis->select($this->config['database']);
99+
}
104100
}
105101

106-
/**
107-
* {@inheritdoc}
108-
*/
109102
public function disconnect(): void
110103
{
111104
if ($this->redis) {
112105
$this->redis->close();
113106
}
114107
}
115108

116-
/**
117-
* {@inheritdoc}
118-
*/
119109
public function del(string $key): void
120110
{
121111
$this->redis->del($key);

‎pkg/redis/Redis.php

+11
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ interface Redis
1010
* @param string $key
1111
* @param string $value
1212
*
13+
* @throws ServerException
14+
*
1315
* @return int length of the list
1416
*/
1517
public function lpush(string $key, string $value): int;
@@ -18,23 +20,32 @@ public function lpush(string $key, string $value): int;
1820
* @param string[] $keys
1921
* @param int $timeout in seconds
2022
*
23+
* @throws ServerException
24+
*
2125
* @return RedisResult|null
2226
*/
2327
public function brpop(array $keys, int $timeout): ?RedisResult;
2428

2529
/**
2630
* @param string $key
2731
*
32+
* @throws ServerException
33+
*
2834
* @return RedisResult|null
2935
*/
3036
public function rpop(string $key): ?RedisResult;
3137

38+
/**
39+
* @throws ServerException
40+
*/
3241
public function connect(): void;
3342

3443
public function disconnect(): void;
3544

3645
/**
3746
* @param string $key
47+
*
48+
* @throws ServerException
3849
*/
3950
public function del(string $key): void;
4051
}

‎pkg/redis/RedisConnectionFactory.php

+67-69
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Enqueue\Redis;
66

7+
use Enqueue\Dsn\Dsn;
78
use Interop\Queue\PsrConnectionFactory;
89
use Interop\Queue\PsrContext;
910

@@ -20,25 +21,29 @@ class RedisConnectionFactory implements PsrConnectionFactory
2021
private $redis;
2122

2223
/**
24+
* @see https://github.com/nrk/predis/wiki/Connection-Parameters
25+
*
2326
* $config = [
24-
* 'host' => can be a host, or the path to a unix domain socket
25-
* 'port' => optional
26-
* 'timeout' => value in seconds (optional, default is 0.0 meaning unlimited)
27-
* 'reserved' => should be null if $retry_interval is specified
28-
* 'retry_interval' => retry interval in milliseconds.
29-
* 'vendor' => 'The library used internally to interact with Redis server
30-
* 'redis' => 'Used only if vendor is custom, should contain an instance of \Enqueue\Redis\Redis interface.
31-
* 'persisted' => bool, Whether it use single persisted connection or open a new one for every context
32-
* 'lazy' => the connection will be performed as later as possible, if the option set to true
33-
* 'database' => Database index to select when connected (default value: 0)
34-
* user - The user name to use.
35-
* pass - Password.
27+
* 'dsn' => A redis DSN string.
28+
* 'scheme' => Specifies the protocol used to communicate with an instance of Redis.
29+
* 'host' => IP or hostname of the target server.
30+
* 'port' => TCP/IP port of the target server.
31+
* 'path' => Path of the UNIX domain socket file used when connecting to Redis using UNIX domain sockets.
32+
* 'database' => Accepts a numeric value that is used by Predis to automatically select a logical database with the SELECT command.
33+
* 'password' => Accepts a value used to authenticate with a Redis server protected by password with the AUTH command.
34+
* 'async' => Specifies if connections to the server is estabilished in a non-blocking way (that is, the client is not blocked while the underlying resource performs the actual connection).
35+
* 'persistent' => Specifies if the underlying connection resource should be left open when a script ends its lifecycle.
36+
* 'lazy' => The connection will be performed as later as possible, if the option set to true
37+
* 'timeout' => Timeout (expressed in seconds) used to connect to a Redis server after which an exception is thrown.
38+
* 'read_write_timeout' => Timeout (expressed in seconds) used when performing read or write operations on the underlying network resource after which an exception is thrown.
39+
* 'predis_options' => An array of predis specific options.
40+
* 'ssl' => could be any of http://fi2.php.net/manual/en/context.ssl.php#refsect1-context.ssl-options
3641
* ].
3742
*
3843
* or
3944
*
40-
* redis:
41-
* redis:?vendor=predis
45+
* redis://h:asdfqwer1234asdf@ec2-111-1-1-1.compute-1.amazonaws.com:111
46+
* tls://127.0.0.1?ssl[cafile]=private.pem&ssl[verify_peer]=1
4247
*
4348
* or
4449
*
@@ -48,32 +53,28 @@ class RedisConnectionFactory implements PsrConnectionFactory
4853
*/
4954
public function __construct($config = 'redis:')
5055
{
51-
if ($config instanceof Redis) {
56+
if ($config instanceof Redis) {
5257
$this->redis = $config;
5358
$this->config = $this->defaultConfig();
5459

5560
return;
5661
}
5762

58-
if (empty($config) || 'redis:' === $config) {
63+
if (empty($config)) {
5964
$config = [];
6065
} elseif (is_string($config)) {
6166
$config = $this->parseDsn($config);
6267
} elseif (is_array($config)) {
68+
if (array_key_exists('dsn', $config)) {
69+
$config = array_replace_recursive($config, $this->parseDsn($config['dsn']));
70+
71+
unset($config['dsn']);
72+
}
6373
} else {
64-
throw new \LogicException('The config must be either an array of options, a DSN string or null');
74+
throw new \LogicException(sprintf('The config must be either an array of options, a DSN string, null or instance of %s', Redis::class));
6575
}
6676

6777
$this->config = array_replace($this->defaultConfig(), $config);
68-
69-
$supportedVendors = ['predis', 'phpredis', 'custom'];
70-
if (false == in_array($this->config['vendor'], $supportedVendors, true)) {
71-
throw new \LogicException(sprintf(
72-
'Unsupported redis vendor given. It must be either "%s". Got "%s"',
73-
implode('", "', $supportedVendors),
74-
$this->config['vendor']
75-
));
76-
}
7778
}
7879

7980
/**
@@ -93,26 +94,14 @@ public function createContext(): PsrContext
9394
private function createRedis(): Redis
9495
{
9596
if (false == $this->redis) {
96-
if ('phpredis' == $this->config['vendor'] && false == $this->redis) {
97+
if (in_array('predis', $this->config['scheme_extensions'], true)) {
98+
$this->redis = new PRedis($this->config);
99+
} elseif (in_array('phpredis', $this->config['scheme_extensions'], true)) {
97100
$this->redis = new PhpRedis($this->config);
98-
}
99-
100-
if ('predis' == $this->config['vendor'] && false == $this->redis) {
101+
} else {
101102
$this->redis = new PRedis($this->config);
102103
}
103104

104-
if ('custom' == $this->config['vendor'] && false == $this->redis) {
105-
if (empty($this->config['redis'])) {
106-
throw new \LogicException('The redis option should be set if vendor is custom.');
107-
}
108-
109-
if (false == $this->config['redis'] instanceof Redis) {
110-
throw new \LogicException(sprintf('The redis option should be instance of "%s".', Redis::class));
111-
}
112-
113-
$this->redis = $this->config['redis'];
114-
}
115-
116105
$this->redis->connect();
117106
}
118107

@@ -121,47 +110,56 @@ private function createRedis(): Redis
121110

122111
private function parseDsn(string $dsn): array
123112
{
124-
if ((false === strpos($dsn, 'redis:')) and (false === strpos($dsn, 'rediss:'))) {
125-
throw new \LogicException(sprintf('The given DSN "%s" is not supported. Must start with "redis:" or "rediss:".', $dsn));
126-
}
127-
128-
if (false === $config = parse_url($dsn)) {
129-
throw new \LogicException(sprintf('Failed to parse DSN "%s"', $dsn));
130-
}
113+
$dsn = new Dsn($dsn);
131114

132-
if (array_key_exists('port', $config)) {
133-
$config['port'] = (int) $config['port'];
115+
$supportedSchemes = ['redis', 'rediss', 'tcp', 'tls', 'unix'];
116+
if (false == in_array($dsn->getSchemeProtocol(), $supportedSchemes, true)) {
117+
throw new \LogicException(sprintf(
118+
'The given scheme protocol "%s" is not supported. It must be one of "%s"',
119+
$dsn->getSchemeProtocol(),
120+
implode('", "', $supportedSchemes)
121+
));
134122
}
135123

136-
if ($query = parse_url($dsn, PHP_URL_QUERY)) {
137-
$queryConfig = [];
138-
parse_str($query, $queryConfig);
124+
$database = $dsn->getInt('database');
139125

140-
$config = array_replace($queryConfig, $config);
126+
// try use path as database name if not set.
127+
if (null === $database && 'unix' !== $dsn->getSchemeProtocol() && null !== $dsn->getPath()) {
128+
$database = (int) ltrim($dsn->getPath(), '/');
141129
}
142130

143-
unset($config['query']);
144-
145-
$config['lazy'] = empty($config['lazy']) ? false : true;
146-
$config['persisted'] = empty($config['persisted']) ? false : true;
147-
148-
return $config;
131+
return array_filter(array_replace($dsn->getQuery(), [
132+
'scheme' => $dsn->getSchemeProtocol(),
133+
'scheme_extensions' => $dsn->getSchemeExtensions(),
134+
'host' => $dsn->getHost(),
135+
'port' => $dsn->getPort(),
136+
'path' => $dsn->getPath(),
137+
'database' => $database,
138+
'password' => $dsn->getPassword(),
139+
'async' => $dsn->getBool('async'),
140+
'persistent' => $dsn->getBool('persistent'),
141+
'timeout' => $dsn->getFloat('timeout'),
142+
'read_write_timeout' => $dsn->getFloat('read_write_timeout'),
143+
]), function ($value) { return null !== $value; });
149144
}
150145

151146
private function defaultConfig(): array
152147
{
153148
return [
154-
'host' => 'localhost',
155149
'scheme' => 'redis',
150+
'scheme_extensions' => [],
151+
'host' => '127.0.0.1',
156152
'port' => 6379,
157-
'timeout' => null,
158-
'reserved' => null,
159-
'retry_interval' => null,
160-
'vendor' => 'phpredis',
161-
'redis' => null,
162-
'persisted' => false,
153+
'path' => null,
154+
'database' => null,
155+
'password' => null,
156+
'async' => false,
157+
'persistent' => false,
163158
'lazy' => true,
164-
'database' => 0,
159+
'timeout' => 5.0,
160+
'read_write_timeout' => null,
161+
'predis_options' => null,
162+
'ssl' => null,
165163
];
166164
}
167165
}

‎pkg/redis/Symfony/RedisTransportFactory.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ public function addConfiguration(ArrayNodeDefinition $builder)
5757
->cannotBeEmpty()
5858
->info('A custom redis service id, used with vendor true only')
5959
->end()
60-
->booleanNode('persisted')
60+
->booleanNode('persistent')
6161
->defaultFalse()
62-
->info('bool, Whether it use single persisted connection or open a new one for every context')
62+
->info('bool, Whether it use single persistent connection or open a new one for every context')
6363
->end()
6464
->booleanNode('lazy')
6565
->defaultTrue()

‎pkg/redis/Tests/RedisConnectionFactoryConfigTest.php

+185-82
Original file line numberDiff line numberDiff line change
@@ -17,33 +17,25 @@ class RedisConnectionFactoryConfigTest extends TestCase
1717
public function testThrowNeitherArrayStringNorNullGivenAsConfig()
1818
{
1919
$this->expectException(\LogicException::class);
20-
$this->expectExceptionMessage('The config must be either an array of options, a DSN string or null');
20+
$this->expectExceptionMessage('The config must be either an array of options, a DSN string, null or instance of Enqueue\Redis\Redis');
2121

2222
new RedisConnectionFactory(new \stdClass());
2323
}
2424

2525
public function testThrowIfSchemeIsNotAmqp()
2626
{
2727
$this->expectException(\LogicException::class);
28-
$this->expectExceptionMessage('The given DSN "http://example.com" is not supported. Must start with "redis:" or "rediss:".');
28+
$this->expectExceptionMessage('The given scheme protocol "http" is not supported. It must be one of "redis", "rediss", "tcp", "tls", "unix"');
2929

3030
new RedisConnectionFactory('http://example.com');
3131
}
3232

3333
public function testThrowIfDsnCouldNotBeParsed()
3434
{
3535
$this->expectException(\LogicException::class);
36-
$this->expectExceptionMessage('Failed to parse DSN "redis://:@/"');
36+
$this->expectExceptionMessage('The DSN is invalid.');
3737

38-
new RedisConnectionFactory('redis://:@/');
39-
}
40-
41-
public function testThrowIfVendorIsInvalid()
42-
{
43-
$this->expectException(\LogicException::class);
44-
$this->expectExceptionMessage('Unsupported redis vendor given. It must be either "predis", "phpredis", "custom". Got "invalidVendor"');
45-
46-
new RedisConnectionFactory(['vendor' => 'invalidVendor']);
38+
new RedisConnectionFactory('foo');
4739
}
4840

4941
public function testCouldBeCreatedWithRedisInstance()
@@ -59,10 +51,10 @@ public function testCouldBeCreatedWithRedisInstance()
5951

6052
public function testThrowIfRedissConnectionUsedWithPhpRedisExtension()
6153
{
62-
$factory = new RedisConnectionFactory('rediss:?vendor=phpredis');
54+
$factory = new RedisConnectionFactory('rediss+phpredis:?lazy=0');
6355

6456
$this->expectException(\LogicException::class);
65-
$this->expectExceptionMessage('The phpredis extension does not support secured connections. Try to use predis library as vendor.');
57+
$this->expectExceptionMessage('The given scheme protocol "rediss" is not supported by php extension. It must be one of "redis", "tcp", "unix"');
6658
$factory->createContext();
6759
}
6860

@@ -84,107 +76,189 @@ public static function provideConfigs()
8476
yield [
8577
null,
8678
[
87-
'host' => 'localhost',
79+
'host' => '127.0.0.1',
8880
'scheme' => 'redis',
8981
'port' => 6379,
90-
'timeout' => null,
91-
'reserved' => null,
92-
'retry_interval' => null,
93-
'vendor' => 'phpredis',
94-
'persisted' => false,
82+
'timeout' => 5.,
83+
'database' => null,
84+
'password' => null,
85+
'scheme_extensions' => [],
86+
'path' => null,
87+
'async' => false,
88+
'persistent' => false,
9589
'lazy' => true,
96-
'database' => 0,
97-
'redis' => null,
90+
'read_write_timeout' => null,
91+
'predis_options' => null,
92+
'ssl' => null,
9893
],
9994
];
10095

10196
yield [
10297
'redis:',
10398
[
104-
'host' => 'localhost',
99+
'host' => '127.0.0.1',
105100
'scheme' => 'redis',
106101
'port' => 6379,
107-
'timeout' => null,
108-
'reserved' => null,
109-
'retry_interval' => null,
110-
'vendor' => 'phpredis',
111-
'persisted' => false,
102+
'timeout' => 5.,
103+
'database' => null,
104+
'password' => null,
105+
'scheme_extensions' => [],
106+
'path' => null,
107+
'async' => false,
108+
'persistent' => false,
112109
'lazy' => true,
113-
'database' => 0,
114-
'redis' => null,
110+
'read_write_timeout' => null,
111+
'predis_options' => null,
112+
'ssl' => null,
115113
],
116114
];
117115

118116
yield [
119117
[],
120118
[
121-
'host' => 'localhost',
119+
'host' => '127.0.0.1',
122120
'scheme' => 'redis',
123121
'port' => 6379,
124-
'timeout' => null,
125-
'reserved' => null,
126-
'retry_interval' => null,
127-
'vendor' => 'phpredis',
128-
'persisted' => false,
122+
'timeout' => 5.,
123+
'database' => null,
124+
'password' => null,
125+
'scheme_extensions' => [],
126+
'path' => null,
127+
'async' => false,
128+
'persistent' => false,
129129
'lazy' => true,
130-
'database' => 0,
131-
'redis' => null,
130+
'read_write_timeout' => null,
131+
'predis_options' => null,
132+
'ssl' => null,
132133
],
133134
];
134135

135136
yield [
136-
'redis://localhost:1234?foo=bar&lazy=0&persisted=true&database=5',
137+
'unix:/path/to/redis.sock?foo=bar&database=5',
137138
[
138-
'host' => 'localhost',
139+
'host' => '127.0.0.1',
140+
'scheme' => 'unix',
141+
'port' => 6379,
142+
'timeout' => 5.,
143+
'database' => 5,
144+
'password' => null,
145+
'scheme_extensions' => [],
146+
'path' => '/path/to/redis.sock',
147+
'async' => false,
148+
'persistent' => false,
149+
'lazy' => true,
150+
'read_write_timeout' => null,
151+
'predis_options' => null,
152+
'ssl' => null,
153+
'foo' => 'bar',
154+
],
155+
];
156+
157+
yield [
158+
['dsn' => 'redis://expectedHost:1234/5', 'host' => 'shouldBeOverwrittenHost', 'foo' => 'bar'],
159+
[
160+
'host' => 'expectedHost',
139161
'scheme' => 'redis',
140162
'port' => 1234,
141-
'timeout' => null,
142-
'reserved' => null,
143-
'retry_interval' => null,
144-
'vendor' => 'phpredis',
145-
'persisted' => true,
146-
'lazy' => false,
163+
'timeout' => 5.,
164+
'database' => 5,
165+
'password' => null,
166+
'scheme_extensions' => [],
167+
'path' => '/5',
168+
'async' => false,
169+
'persistent' => false,
170+
'lazy' => true,
171+
'read_write_timeout' => null,
172+
'predis_options' => null,
173+
'ssl' => null,
147174
'foo' => 'bar',
175+
],
176+
];
177+
178+
yield [
179+
'redis+predis://localhost:1234/5?foo=bar&persistent=true',
180+
[
181+
'host' => 'localhost',
182+
'scheme' => 'redis',
183+
'port' => 1234,
184+
'timeout' => 5.,
148185
'database' => 5,
149-
'redis' => null,
186+
'password' => null,
187+
'scheme_extensions' => ['predis'],
188+
'path' => '/5',
189+
'async' => false,
190+
'persistent' => true,
191+
'lazy' => true,
192+
'read_write_timeout' => null,
193+
'predis_options' => null,
194+
'ssl' => null,
195+
'foo' => 'bar',
196+
],
197+
];
198+
199+
//check normal redis connection for php redis extension
200+
yield [
201+
'redis+phpredis://localhost:1234?foo=bar',
202+
[
203+
'host' => 'localhost',
204+
'scheme' => 'redis',
205+
'port' => 1234,
206+
'timeout' => 5.,
207+
'database' => null,
208+
'password' => null,
209+
'scheme_extensions' => ['phpredis'],
210+
'path' => null,
211+
'async' => false,
212+
'persistent' => false,
213+
'lazy' => true,
214+
'read_write_timeout' => null,
215+
'predis_options' => null,
216+
'ssl' => null,
217+
'foo' => 'bar',
150218
],
151219
];
152220

153221
//check normal redis connection for predis library
154222
yield [
155-
'redis://localhost:1234?foo=bar&lazy=0&vendor=predis',
223+
'redis+predis://localhost:1234?foo=bar',
156224
[
157225
'host' => 'localhost',
158226
'scheme' => 'redis',
159227
'port' => 1234,
160-
'timeout' => null,
161-
'reserved' => null,
162-
'retry_interval' => null,
163-
'vendor' => 'predis',
164-
'persisted' => false,
165-
'lazy' => false,
228+
'timeout' => 5.,
229+
'database' => null,
230+
'password' => null,
231+
'scheme_extensions' => ['predis'],
232+
'path' => null,
233+
'async' => false,
234+
'persistent' => false,
235+
'lazy' => true,
236+
'read_write_timeout' => null,
237+
'predis_options' => null,
238+
'ssl' => null,
166239
'foo' => 'bar',
167-
'database' => 0,
168-
'redis' => null,
169240
],
170241
];
171242

172243
//check tls connection for predis library
173244
yield [
174-
'rediss://localhost:1234?foo=bar&lazy=0&vendor=predis',
245+
'rediss+predis://localhost:1234?foo=bar&async=1',
175246
[
176247
'host' => 'localhost',
177248
'scheme' => 'rediss',
178249
'port' => 1234,
179-
'timeout' => null,
180-
'reserved' => null,
181-
'retry_interval' => null,
182-
'vendor' => 'predis',
183-
'persisted' => false,
184-
'lazy' => false,
250+
'timeout' => 5.,
251+
'database' => null,
252+
'password' => null,
253+
'scheme_extensions' => ['predis'],
254+
'path' => null,
255+
'async' => true,
256+
'persistent' => false,
257+
'lazy' => true,
258+
'read_write_timeout' => null,
259+
'predis_options' => null,
260+
'ssl' => null,
185261
'foo' => 'bar',
186-
'database' => 0,
187-
'redis' => null,
188262
],
189263
];
190264

@@ -194,15 +268,18 @@ public static function provideConfigs()
194268
'host' => 'localhost',
195269
'scheme' => 'redis',
196270
'port' => 1234,
197-
'timeout' => null,
198-
'reserved' => null,
199-
'retry_interval' => null,
200-
'vendor' => 'phpredis',
201-
'persisted' => false,
271+
'timeout' => 5.,
272+
'database' => null,
273+
'password' => null,
274+
'scheme_extensions' => [],
275+
'path' => null,
276+
'async' => false,
277+
'persistent' => false,
202278
'lazy' => true,
279+
'read_write_timeout' => null,
280+
'predis_options' => null,
281+
'ssl' => null,
203282
'foo' => 'bar',
204-
'database' => 0,
205-
'redis' => null,
206283
],
207284
];
208285

@@ -213,16 +290,42 @@ public static function provideConfigs()
213290
'host' => 'ec2-111-1-1-1.compute-1.amazonaws.com',
214291
'scheme' => 'redis',
215292
'port' => 111,
216-
'timeout' => null,
217-
'reserved' => null,
218-
'retry_interval' => null,
219-
'vendor' => 'phpredis',
220-
'persisted' => false,
221-
'lazy' => false,
222-
'database' => 0,
223-
'redis' => null,
224-
'user' => 'h',
225-
'pass' => 'asdfqwer1234asdf',
293+
'timeout' => 5.,
294+
'database' => null,
295+
'password' => 'asdfqwer1234asdf',
296+
'scheme_extensions' => [],
297+
'path' => null,
298+
'async' => false,
299+
'persistent' => false,
300+
'lazy' => true,
301+
'read_write_timeout' => null,
302+
'predis_options' => null,
303+
'ssl' => null,
304+
],
305+
];
306+
307+
// from predis doc
308+
309+
yield [
310+
'tls://127.0.0.1?ssl[cafile]=private.pem&ssl[verify_peer]=1',
311+
[
312+
'host' => '127.0.0.1',
313+
'scheme' => 'tls',
314+
'port' => 6379,
315+
'timeout' => 5.,
316+
'database' => null,
317+
'scheme_extensions' => [],
318+
'path' => null,
319+
'async' => false,
320+
'persistent' => false,
321+
'lazy' => true,
322+
'read_write_timeout' => null,
323+
'predis_options' => null,
324+
'password' => null,
325+
'ssl' => [
326+
'cafile' => 'private.pem',
327+
'verify_peer' => '1',
328+
],
226329
],
227330
];
228331
}

‎pkg/redis/Tests/RedisConnectionFactoryTest.php

-42
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace Enqueue\Redis\Tests;
44

5-
use Enqueue\Redis\Redis;
65
use Enqueue\Redis\RedisConnectionFactory;
76
use Enqueue\Redis\RedisContext;
87
use Enqueue\Test\ClassExtensionTrait;
@@ -29,45 +28,4 @@ public function testShouldCreateLazyContext()
2928
$this->assertAttributeEquals(null, 'redis', $context);
3029
$this->assertInternalType('callable', $this->readAttribute($context, 'redisFactory'));
3130
}
32-
33-
public function testShouldThrowIfVendorIsCustomButRedisInstanceNotSet()
34-
{
35-
$factory = new RedisConnectionFactory([
36-
'vendor' => 'custom',
37-
'redis' => null,
38-
'lazy' => false,
39-
]);
40-
41-
$this->expectException(\LogicException::class);
42-
$this->expectExceptionMessage('The redis option should be set if vendor is custom.');
43-
$factory->createContext();
44-
}
45-
46-
public function testShouldThrowIfVendorIsCustomButRedisIsNotInstanceOfRedis()
47-
{
48-
$factory = new RedisConnectionFactory([
49-
'vendor' => 'custom',
50-
'redis' => new \stdClass(),
51-
'lazy' => false,
52-
]);
53-
54-
$this->expectException(\LogicException::class);
55-
$this->expectExceptionMessage('The redis option should be instance of "Enqueue\Redis\Redis".');
56-
$factory->createContext();
57-
}
58-
59-
public function testShouldUseCustomRedisInstance()
60-
{
61-
$redisMock = $this->createMock(Redis::class);
62-
63-
$factory = new RedisConnectionFactory([
64-
'vendor' => 'custom',
65-
'redis' => $redisMock,
66-
'lazy' => false,
67-
]);
68-
69-
$context = $factory->createContext();
70-
71-
$this->assertAttributeSame($redisMock, 'redis', $context);
72-
}
7331
}

‎pkg/redis/Tests/Symfony/RedisTransportFactoryTest.php

+5-5
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,15 @@ public function testShouldAllowAddConfiguration()
4848
'host' => 'localhost',
4949
'port' => 123,
5050
'vendor' => 'phpredis',
51-
'persisted' => true,
51+
'persistent' => true,
5252
'lazy' => false,
5353
]]);
5454

5555
$this->assertEquals([
5656
'host' => 'localhost',
5757
'port' => 123,
5858
'vendor' => 'phpredis',
59-
'persisted' => true,
59+
'persistent' => true,
6060
'lazy' => false,
6161
'database' => 0,
6262
], $config);
@@ -71,14 +71,14 @@ public function testShouldAllowAddConfigurationFromDSN()
7171
$transport->addConfiguration($rootNode);
7272
$processor = new Processor();
7373
$config = $processor->process($tb->buildTree(), [[
74-
'dsn' => 'redis://localhost:8080?vendor=predis&persisted=false&lazy=true&database=5',
74+
'dsn' => 'redis://localhost:8080?vendor=predis&persistent=false&lazy=true&database=5',
7575
]]);
7676

7777
$this->assertEquals([
78-
'persisted' => false,
78+
'persistent' => false,
7979
'lazy' => true,
8080
'database' => 0,
81-
'dsn' => 'redis://localhost:8080?vendor=predis&persisted=false&lazy=true&database=5',
81+
'dsn' => 'redis://localhost:8080?vendor=predis&persistent=false&lazy=true&database=5',
8282
], $config);
8383
}
8484

‎pkg/redis/composer.json

+5-8
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,16 @@
77
"license": "MIT",
88
"require": {
99
"php": "^7.1.3",
10-
"queue-interop/queue-interop": "0.7.x-dev"
10+
"queue-interop/queue-interop": "0.7.x-dev",
11+
"enqueue/dsn": "0.9.x-dev",
12+
"predis/predis": "^1.1"
1113
},
1214
"require-dev": {
1315
"phpunit/phpunit": "~5.4.0",
1416
"predis/predis": "^1.1",
1517
"enqueue/test": "0.9.x-dev",
16-
"enqueue/enqueue": "0.9.x-dev",
1718
"enqueue/null": "0.9.x-dev",
18-
"queue-interop/queue-spec": "0.6.x-dev",
19-
"symfony/dependency-injection": "^3.4|^4",
20-
"symfony/config": "^3.4|^4"
19+
"queue-interop/queue-spec": "0.6.x-dev"
2120
},
2221
"support": {
2322
"email": "opensource@forma-pro.com",
@@ -33,9 +32,7 @@
3332
]
3433
},
3534
"suggest": {
36-
"enqueue/enqueue": "If you'd like to use advanced features like Client abstract layer or Symfony integration features",
37-
"predis/predis": "Either this PHP library or redis extension has to be installed.",
38-
"ext-redis": "Either this PHP extension or predis/predis extension has to be installed."
35+
"ext-redis": "If you'd like to use phpredis extension."
3936
},
4037
"minimum-stability": "dev",
4138
"extra": {

‎pkg/test/RedisExtension.php

+20-24
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,42 @@
22

33
namespace Enqueue\Test;
44

5+
use Enqueue\Redis\PhpRedis;
6+
use Enqueue\Redis\PRedis;
57
use Enqueue\Redis\RedisConnectionFactory;
68
use Enqueue\Redis\RedisContext;
79

810
trait RedisExtension
911
{
10-
/**
11-
* @return RedisContext
12-
*/
13-
private function buildPhpRedisContext()
12+
private function buildPhpRedisContext(): RedisContext
1413
{
15-
if (false == getenv('REDIS_HOST')) {
14+
if (false == getenv('PHPREDIS_DSN')) {
1615
throw new \PHPUnit_Framework_SkippedTestError('Functional tests are not allowed in this environment');
1716
}
1817

19-
$config = [
20-
'host' => getenv('REDIS_HOST'),
21-
'port' => (int) getenv('REDIS_PORT'),
22-
'vendor' => 'phpredis',
23-
'lazy' => false,
24-
];
18+
$config = getenv('PHPREDIS_DSN');
2519

26-
return (new RedisConnectionFactory($config))->createContext();
20+
$context = (new RedisConnectionFactory($config))->createContext();
21+
22+
//guard
23+
$this->assertInstanceOf(PhpRedis::class, $context->getRedis());
24+
25+
return $context;
2726
}
2827

29-
/**
30-
* @return RedisContext
31-
*/
32-
private function buildPRedisContext()
28+
private function buildPRedisContext(): RedisContext
3329
{
34-
if (false == getenv('REDIS_HOST')) {
30+
if (false == getenv('PREDIS_DSN')) {
3531
throw new \PHPUnit_Framework_SkippedTestError('Functional tests are not allowed in this environment');
3632
}
3733

38-
$config = [
39-
'host' => getenv('REDIS_HOST'),
40-
'port' => getenv('REDIS_PORT'),
41-
'vendor' => 'predis',
42-
'lazy' => false,
43-
];
34+
$config = getenv('PREDIS_DSN');
35+
36+
$context = (new RedisConnectionFactory($config))->createContext();
37+
38+
//guard
39+
$this->assertInstanceOf(PRedis::class, $context->getRedis());
4440

45-
return (new RedisConnectionFactory($config))->createContext();
41+
return $context;
4642
}
4743
}

0 commit comments

Comments
 (0)
Please sign in to comment.