@@ -74,4 +74,57 @@ public static function provideCreateConnection(): array
7474            ],
7575        ];
7676    }
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+     }
77130}
0 commit comments