3333/**
3434 * @implements ConnectionPoolInterface<BoltConnection>
3535 */
36- final class ConnectionPool implements ConnectionPoolInterface
36+ class ConnectionPool implements ConnectionPoolInterface
3737{
3838 /** @var list<BoltConnection> */
3939 private array $ activeConnections = [];
@@ -45,6 +45,7 @@ public function __construct(
4545 private readonly ?Neo4jLogger $ logger ,
4646 private readonly float $ acquireConnectionTimeout ,
4747 private readonly float $ connectionTimeout ,
48+ private readonly float $ maxConnectionLifetime ,
4849 ) {
4950 }
5051
@@ -66,7 +67,8 @@ public static function create(
6667 ),
6768 $ conf ->getLogger (),
6869 $ conf ->getAcquireConnectionTimeout (),
69- $ conf ->getConnectionTimeout ()
70+ $ conf ->getConnectionTimeout (),
71+ $ conf ->getMaxConnectionLifetime ()
7072 );
7173 }
7274
@@ -106,9 +108,10 @@ public function acquire(SessionConfiguration $config): Generator
106108 }
107109
108110 try {
109- $ connection = $ this ->factory ->createConnection ($ this ->data , $ config , $ this ->connectionTimeout );
111+ $ connection = $ this ->factory ->createConnection ($ this ->data , $ config , $ this ->connectionTimeout , $ this -> maxConnectionLifetime );
110112
111113 $ this ->activeConnections [] = $ connection ;
114+
112115 return $ connection ;
113116 } catch (ConnectionTimeoutException $ e ) {
114117 throw new TimeoutException ($ e ->getMessage (), $ e ->getCode (), $ e );
@@ -138,9 +141,15 @@ private function reuseConnectionIfPossible(SessionConfiguration $config): ?BoltC
138141 {
139142 // Ensure random connection reuse before picking one.
140143 shuffle ($ this ->activeConnections );
141- foreach ($ this ->activeConnections as $ activeConnection ) {
144+ foreach ($ this ->activeConnections as $ index => $ activeConnection ) {
142145 // We prefer a connection that is just ready
143146 if ($ activeConnection ->getServerState () === 'READY ' && $ this ->factory ->canReuseConnection ($ activeConnection , $ config )) {
147+ if ($ this ->isConnectionExpired ($ activeConnection )) {
148+ $ activeConnection ->close ();
149+ unset($ this ->activeConnections [$ index ]); // Remove expired connection
150+ continue ;
151+ }
152+
144153 return $ this ->factory ->reuseConnection ($ activeConnection , $ config );
145154 }
146155 }
@@ -155,4 +164,12 @@ public function close(): void
155164 }
156165 $ this ->activeConnections = [];
157166 }
167+
168+ public function isConnectionExpired (BoltConnection $ activeConnection ): bool
169+ {
170+ $ now = (int ) (microtime (true ) * 1000 );
171+ $ timeSinceCreatedInSeconds = (int ) (($ now - $ activeConnection ->getCreatedAtMillis ()) / 1000 );
172+
173+ return $ timeSinceCreatedInSeconds >= $ this ->maxConnectionLifetime ;
174+ }
158175}
0 commit comments