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