Skip to content

fix(db): a lease released after interrupt decrements the pool entry that replaced it #1213

Description

@ZhuchkaTriplesix

Part of #1212.

Problem

A lease is released by key, not by the pool entry it was taken from.

  • PgLease.release() calls _pool._release(_key) (lib/core/database/postgres_connection_pool.dart:44-49). _release looks up _pool[k] and decrements its refs (:156-169).
  • interrupt() removes the entry and force-closes its connection (:173-180 → _removeEntryClosing). Leases taken before still point at the closed connection, but the key is free.
  • The next acquire() with that key creates a new entry. When an old lease is released afterwards, _release finds the new entry by key and decrements its refs.

Effects:

  • refs of the new entry reaches 0 while a caller still uses it. The idle timer (defaultIdleDisposeDelay, 4 s, :63) then disconnects the session under that caller: Not connected to PostgreSQL on the next statement, seconds after an unrelated action.
  • refs can go negative; later releases and the idle timer no longer match the real number of users.

The same code exists in MysqlConnectionPool._release (lib/core/database/mysql_connection_pool.dart:143) and SqliteConnectionPool._release (lib/core/database/sqlite_connection_pool.dart:150).

interrupt() runs often: every table tab dispose (#1215), the SQL editor's Cancel (PostgresSqlExecutionDelegate.cancelQuery, lib/features/postgresql/postgres_sql_workspace.dart:163-171), and the timeout paths.

Scope

  • A lease keeps a reference to the _PoolEntry it was given (or the entry's generation number). release() decrements only that entry; if the entry is no longer in the pool, release is a no-op.
  • Apply to all three pools. Consider one generic pool implementation for the three drivers, since the bookkeeping is identical.
  • Debug assert that refs never goes below 0.

Acceptance

  • Unit test per pool (fake connection factory): acquire lease A, interrupt, acquire lease B (new entry), release A → B's refs is still 1 and B is not disconnected after the idle delay.
  • Unit test: releasing a lease twice, or after disconnectAll, changes nothing.
  • refs cannot become negative (assert covered by a test).

Activity

  1. added
    bugSomething isn't working
    stabilityTheme parser epic label: stability
    coreCore library logic and services
    connectionsDatabase connections, URI parsing, pools
    P1High priority / Core capability
    on Oct 9, 2026
  2. added 2 commits that reference this issue on Oct 9, 2026
  3. ZhuchkaTriplesix commented on Oct 9, 2026

    @ZhuchkaTriplesix
    MemberAuthor

    Closed by #1219.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High priority / Core capabilitybugSomething isn't workingconnectionsDatabase connections, URI parsing, poolscoreCore library logic and servicesstabilityTheme parser epic label: stability

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions