@@ -74,4 +74,57 @@ public static function provideCreateConnection(): array
74
74
],
75
75
];
76
76
}
77
+
78
+ /**
79
+ * Due to a bug in phpredis, the persistent connection will keep its last selected database. So when re-using
80
+ * a persistent connection, the database has to be re-selected, too.
81
+ *
82
+ * @see https://github.com/phpredis/phpredis/issues/1920
83
+ *
84
+ * @group integration
85
+ */
86
+ public function testPconnectSelectsCorrectDatabase ()
87
+ {
88
+ if (!class_exists (\Redis::class)) {
89
+ throw new SkippedTestSuiteError ('The "Redis" class is required. ' );
90
+ }
91
+ if (!getenv ('REDIS_HOST ' )) {
92
+ throw new SkippedTestSuiteError ('REDIS_HOST env var is not defined. ' );
93
+ }
94
+ if (!\ini_get ('redis.pconnect.pooling_enabled ' )) {
95
+ throw new SkippedTestSuiteError ('The bug only occurs when pooling is enabled. ' );
96
+ }
97
+
98
+ // Limit the connection pool size to 1:
99
+ if (false === $ prevPoolSize = ini_set ('redis.pconnect.connection_limit ' , 1 )) {
100
+ throw new SkippedTestSuiteError ('Unable to set pool size ' );
101
+ }
102
+
103
+ try {
104
+ $ mock = self ::getObjectForTrait (RedisTrait::class);
105
+
106
+ $ dsn = 'redis:// ' .getenv ('REDIS_HOST ' );
107
+
108
+ $ cacheKey = 'testPconnectSelectsCorrectDatabase ' ;
109
+ $ cacheValueOnDb1 = 'I should only be on database 1 ' ;
110
+
111
+ // First connect to database 1 and set a value there so we can identify this database:
112
+ $ db1 = $ mock ::createConnection ($ dsn , ['dbindex ' => 1 , 'persistent ' => 1 ]);
113
+ self ::assertInstanceOf (\Redis::class, $ db1 );
114
+ self ::assertSame (1 , $ db1 ->getDbNum ());
115
+ $ db1 ->set ($ cacheKey , $ cacheValueOnDb1 );
116
+ self ::assertSame ($ cacheValueOnDb1 , $ db1 ->get ($ cacheKey ));
117
+
118
+ // Unset the connection - do not use `close()` or we will lose the persistent connection:
119
+ unset($ db1 );
120
+
121
+ // Now connect to database 0 and see that we do not actually ended up on database 1 by checking the value:
122
+ $ db0 = $ mock ::createConnection ($ dsn , ['dbindex ' => 0 , 'persistent ' => 1 ]);
123
+ self ::assertInstanceOf (\Redis::class, $ db0 );
124
+ self ::assertSame (0 , $ db0 ->getDbNum ()); // Redis is lying here! We could actually be on any database!
125
+ self ::assertNotSame ($ cacheValueOnDb1 , $ db0 ->get ($ cacheKey )); // This value should not exist if we are actually on db 0
126
+ } finally {
127
+ ini_set ('redis.pconnect.connection_limit ' , $ prevPoolSize );
128
+ }
129
+ }
77
130
}
0 commit comments