|
23 | 23 | use Doctrine\DBAL\Result; |
24 | 24 | use Doctrine\DBAL\Schema\Schema; |
25 | 25 | use Doctrine\DBAL\Statement; |
| 26 | +use OC\DB\Middleware\ConnectionActivityNotifier; |
26 | 27 | use OC\DB\QueryBuilder\Partitioned\PartitionedQueryBuilder; |
27 | 28 | use OC\DB\QueryBuilder\Partitioned\PartitionSplit; |
28 | 29 | use OC\DB\QueryBuilder\QueryBuilder; |
@@ -131,6 +132,10 @@ public function __construct( |
131 | 132 | parent::__construct($params, $driver, $config, $eventManager); |
132 | 133 | $this->adapter = new $params['adapter']($this); |
133 | 134 | $this->tablePrefix = $params['tablePrefix']; |
| 135 | + $activityNotifier = $params['activity_notifier'] ?? null; |
| 136 | + if ($activityNotifier instanceof ConnectionActivityNotifier) { |
| 137 | + $activityNotifier->setListener($this->refreshLastConnectionCheck(...)); |
| 138 | + } |
134 | 139 | $this->isShardingEnabled = isset($this->params['sharding']) && !empty($this->params['sharding']); |
135 | 140 |
|
136 | 141 | if ($this->isShardingEnabled) { |
@@ -229,7 +234,7 @@ public function connect($connectionName = null) { |
229 | 234 | $status = parent::connect(); |
230 | 235 | $eventLogger->end('connect:db'); |
231 | 236 |
|
232 | | - $this->lastConnectionCheck[$this->getConnectionName()] = time(); |
| 237 | + $this->refreshLastConnectionCheck(); |
233 | 238 |
|
234 | 239 | return $status; |
235 | 240 | } catch (Exception $e) { |
@@ -898,13 +903,24 @@ private function reconnectIfNeeded(): void { |
898 | 903 |
|
899 | 904 | try { |
900 | 905 | $this->_conn->query($this->getDriver()->getDatabasePlatform()->getDummySelectSQL()); |
901 | | - $this->lastConnectionCheck[$this->getConnectionName()] = time(); |
| 906 | + $this->refreshLastConnectionCheck(); |
902 | 907 | } catch (ConnectionLost|\Exception $e) { |
903 | 908 | $this->logger->warning('Exception during connectivity check, closing and reconnecting', ['exception' => $e]); |
904 | 909 | $this->close(); |
905 | 910 | } |
906 | 911 | } |
907 | 912 |
|
| 913 | + /** |
| 914 | + * A successful round trip proves the connection is alive: pushing the idle |
| 915 | + * timer forward keeps the connectivity probe of reconnectIfNeeded() from |
| 916 | + * firing between adjacent operations, where its query would reset the |
| 917 | + * driver level last insert id on MySQL. Invoked for every driver level |
| 918 | + * execution via the ConnectionActivityMiddleware. |
| 919 | + */ |
| 920 | + private function refreshLastConnectionCheck(): void { |
| 921 | + $this->lastConnectionCheck[$this->getConnectionName()] = time(); |
| 922 | + } |
| 923 | + |
908 | 924 | private function getConnectionName(): string { |
909 | 925 | return $this->isConnectedToPrimary() ? 'primary' : 'replica'; |
910 | 926 | } |
|
0 commit comments