Repository navigation
fix(db): reflect underlying driver socket state in isConnected and mark session closed on socket drop #1373
Description
Problem
In PostgresConnection (lib/core/database/postgres_connection.dart, line 162):
bool get isConnected => _isConnected && _conn != null;In MysqlConnection (lib/core/database/mysql_connection.dart, line 169):
bool get isConnected => _isConnected && _conn != null;In RedisConnection (lib/core/database/redis_connection.dart, line 124):
bool get isConnected => _isConnected && _command != null;-
Ghost Connection:
_isConnectedis set totruewhenconnect()completes and is only set tofalseon explicitdisconnect()orforceClose().
When a remote database server closes the connection (idle timeout, server restart, TCP RST/FIN, network drop), the underlying driver socket is closed:- In
package:postgres,_conn.isOpenbecomesfalse. - In
third_party/mysql_client,_conn.connectedbecomesfalse.
However,isConnectedcontinues returningtruebecause_isConnectedremainstrueand_conn != null.
- In
-
Pool Reconnect Bypass:
InPostgresConnectionPoolandMysqlConnectionPool:Future<void> _ensureConnected(_PoolEntry entry, PgSessionMode mode) async { if (entry.connection.isConnected) return; try { await _reconnect(entry, mode); } catch (_) { ... } }
Because
isConnectederroneously returnstrue,_ensureConnectednever calls_reconnect. It hands the dead session to the caller. -
Persistent Error Loop:
Whenexecute(...)runs on the closed socket, it throws a socket / connection exception.execute(...)only catchesTimeoutExceptionto callforceClose(), so socket exceptions bypass cleanup._isConnectedstaystrue, permanently locking the pooled entry in a dead state where every subsequent query fails until the connection is manually invalidated or the app restarted.
Scope
- In
PostgresConnection.isConnected, check_conn != null && _conn!.isOpen. - In
MysqlConnection.isConnected, check_conn != null && _conn!.connected(and listen to_conn!.onClose). - In
RedisConnection.isConnected, verify socket/command stream state. - In
execute(...)of both drivers, catchConnectionLostException/ socket errors and callunawaited(forceClose())so the next call or pool acquire triggers a clean reconnect. - Add unit tests verifying that a closed underlying socket causes
isConnectedto returnfalseand triggers_reconnectin_ensureConnected.
Activity
fix(db): import the mapped exception types in the drivers, await-lint…
Merge pull request #1379 from QueryaHub/fix/1373-reflect-driver-socke…
ZhuchkaTriplesix commentedon Oct 11, 2026
Done in #1379 (merged into
dev).