12
12
namespace Symfony \Component \Cache \Traits ;
13
13
14
14
use Predis \Connection \Aggregate \ClusterInterface ;
15
- use Predis \Connection \Aggregate \PredisCluster ;
16
15
use Predis \Connection \Aggregate \RedisCluster ;
17
16
use Predis \Connection \Factory ;
18
17
use Predis \Response \Status ;
@@ -53,9 +52,7 @@ private function init($redisClient, $namespace, $defaultLifetime, ?MarshallerInt
53
52
if (preg_match ('#[^-+_.A-Za-z0-9]# ' , $ namespace , $ match )) {
54
53
throw new InvalidArgumentException (sprintf ('RedisAdapter namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed. ' , $ match [0 ]));
55
54
}
56
- if ($ redisClient instanceof \RedisCluster) {
57
- $ this ->enableVersioning ();
58
- } elseif (!$ redisClient instanceof \Redis && !$ redisClient instanceof \RedisArray && !$ redisClient instanceof \Predis \Client && !$ redisClient instanceof RedisProxy) {
55
+ if (!$ redisClient instanceof \Redis && !$ redisClient instanceof \RedisArray && !$ redisClient instanceof \RedisCluster && !$ redisClient instanceof \Predis \Client && !$ redisClient instanceof RedisProxy) {
59
56
throw new InvalidArgumentException (sprintf ('%s() expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\Client, %s given ' , __METHOD__ , \is_object ($ redisClient ) ? \get_class ($ redisClient ) : \gettype ($ redisClient )));
60
57
}
61
58
$ this ->redis = $ redisClient ;
@@ -182,18 +179,30 @@ public static function createConnection($dsn, array $options = array())
182
179
*/
183
180
protected function doFetch (array $ ids )
184
181
{
185
- if ($ ids ) {
182
+ if (!$ ids ) {
183
+ return array ();
184
+ }
185
+
186
+ $ i = -1 ;
187
+ $ result = array ();
188
+
189
+ if ($ this ->redis instanceof \Predis \Client) {
186
190
$ values = $ this ->pipeline (function () use ($ ids ) {
187
191
foreach ($ ids as $ id ) {
188
192
yield 'get ' => array ($ id );
189
193
}
190
194
});
191
- foreach ($ values as $ id => $ v ) {
192
- if ($ v ) {
193
- yield $ id => $ this ->marshaller ->unmarshall ($ v );
194
- }
195
+ } else {
196
+ $ values = array_combine ($ ids , $ this ->redis ->mget ($ ids ));
197
+ }
198
+
199
+ foreach ($ values as $ id => $ v ) {
200
+ if ($ v ) {
201
+ $ result [$ id ] = $ this ->marshaller ->unmarshall ($ v );
195
202
}
196
203
}
204
+
205
+ return $ result ;
197
206
}
198
207
199
208
/**
@@ -209,9 +218,6 @@ protected function doHave($id)
209
218
*/
210
219
protected function doClear ($ namespace )
211
220
{
212
- // When using a native Redis cluster, clearing the cache is done by versioning in AbstractTrait::clear().
213
- // This means old keys are not really removed until they expire and may need garbage collection.
214
-
215
221
$ cleared = true ;
216
222
$ hosts = array ($ this ->redis );
217
223
$ evalArgs = array (array ($ namespace ), 0 );
@@ -220,21 +226,23 @@ protected function doClear($namespace)
220
226
$ evalArgs = array (0 , $ namespace );
221
227
222
228
$ connection = $ this ->redis ->getConnection ();
223
- if ($ connection instanceof PredisCluster ) {
229
+ if ($ connection instanceof ClusterInterface && $ connection instanceof \Traversable ) {
224
230
$ hosts = array ();
225
231
foreach ($ connection as $ c ) {
226
232
$ hosts [] = new \Predis \Client ($ c );
227
233
}
228
- } elseif ($ connection instanceof RedisCluster) {
229
- return false ;
230
234
}
231
235
} elseif ($ this ->redis instanceof \RedisArray) {
232
236
$ hosts = array ();
233
237
foreach ($ this ->redis ->_hosts () as $ host ) {
234
238
$ hosts [] = $ this ->redis ->_instance ($ host );
235
239
}
236
240
} elseif ($ this ->redis instanceof \RedisCluster) {
237
- return false ;
241
+ $ hosts = array ();
242
+ foreach ($ this ->redis ->_masters () as $ host ) {
243
+ $ hosts [] = $ h = new \Redis ();
244
+ $ h ->connect ($ host [0 ], $ host [1 ]);
245
+ }
238
246
}
239
247
foreach ($ hosts as $ host ) {
240
248
if (!isset ($ namespace [0 ])) {
@@ -261,7 +269,7 @@ protected function doClear($namespace)
261
269
$ keys = $ keys [1 ];
262
270
}
263
271
if ($ keys ) {
264
- $ host -> del ($ keys );
272
+ $ this -> doDelete ($ keys );
265
273
}
266
274
} while ($ cursor = (int ) $ cursor );
267
275
}
@@ -274,7 +282,17 @@ protected function doClear($namespace)
274
282
*/
275
283
protected function doDelete (array $ ids )
276
284
{
277
- if ($ ids ) {
285
+ if (!$ ids ) {
286
+ return true ;
287
+ }
288
+
289
+ if ($ this ->redis instanceof \Predis \Client) {
290
+ $ this ->pipeline (function () use ($ ids ) {
291
+ foreach ($ ids as $ id ) {
292
+ yield 'del ' => array ($ id );
293
+ }
294
+ })->rewind ();
295
+ } else {
278
296
$ this ->redis ->del ($ ids );
279
297
}
280
298
@@ -312,7 +330,16 @@ private function pipeline(\Closure $generator)
312
330
{
313
331
$ ids = array ();
314
332
315
- if ($ this ->redis instanceof \Predis \Client && !$ this ->redis ->getConnection () instanceof ClusterInterface) {
333
+ if ($ this ->redis instanceof \RedisCluster || ($ this ->redis instanceof \Predis \Client && $ this ->redis ->getConnection () instanceof RedisCluster)) {
334
+ // phpredis & predis don't support pipelining with RedisCluster
335
+ // see https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#pipelining
336
+ // see https://github.com/nrk/predis/issues/267#issuecomment-123781423
337
+ $ results = array ();
338
+ foreach ($ generator () as $ command => $ args ) {
339
+ $ results [] = \call_user_func_array (array ($ this ->redis , $ command ), $ args );
340
+ $ ids [] = $ args [0 ];
341
+ }
342
+ } elseif ($ this ->redis instanceof \Predis \Client) {
316
343
$ results = $ this ->redis ->pipeline (function ($ redis ) use ($ generator , &$ ids ) {
317
344
foreach ($ generator () as $ command => $ args ) {
318
345
\call_user_func_array (array ($ redis , $ command ), $ args );
@@ -336,15 +363,6 @@ private function pipeline(\Closure $generator)
336
363
foreach ($ results as $ k => list ($ h , $ c )) {
337
364
$ results [$ k ] = $ connections [$ h ][$ c ];
338
365
}
339
- } elseif ($ this ->redis instanceof \RedisCluster || ($ this ->redis instanceof \Predis \Client && $ this ->redis ->getConnection () instanceof ClusterInterface)) {
340
- // phpredis & predis don't support pipelining with RedisCluster
341
- // see https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#pipelining
342
- // see https://github.com/nrk/predis/issues/267#issuecomment-123781423
343
- $ results = array ();
344
- foreach ($ generator () as $ command => $ args ) {
345
- $ results [] = \call_user_func_array (array ($ this ->redis , $ command ), $ args );
346
- $ ids [] = $ args [0 ];
347
- }
348
366
} else {
349
367
$ this ->redis ->multi (\Redis::PIPELINE );
350
368
foreach ($ generator () as $ command => $ args ) {
0 commit comments