Skip to content

Connections: give each kind of work its own connection instead of one shared pool #731

Description

@EVWorth

Problem

Every connection profile opens one sqlx pool (default max 5, 10s acquire timeout), and everything shares it:

Who Where
Editor queries query/executor.rs
Schema browsing schema/inspector.rs (18 call sites)
Backups / restores backup/writer.rs, restore/runner.rs, each holding one connection for the whole run
Admin (process list, kill) mas-admin
The agent (MCP) src/mcp/workspace.rs: run and run_ddl through the same executor, stage_write from the same pool, holding row locks for up to the staging deadline

Consequences:

  1. The agent can starve the user. This contradicts FR-6.3.2 in DESIGN_REQUIREMENTS.md: "Each session gets its own pooled connection, timeout and grants, so a runaway agent query cannot starve the user's." It's not implemented: agent traffic uses the user's pool.
  2. A backup occupies a shared slot for its whole run. Add a few schema loads and the editor gets "pool timed out".
  3. The pool-exhausted error can't say what's holding the connections, because nothing tracks it. fix(connection): say what is holding the pool, not just that it is full #727 tries to count in-flight queries, but only editor queries are counted, so ordinary backup and schema activity gets reported as "a bug in SQLPilot".
  4. Editor tabs aren't sessions. Each run can land on a different pooled connection, which is why the executor re-sends USE db before every statement. SET @var, SET SESSION …, temporary tables, and a transaction opened in one run and committed in the next can silently not carry over.

How other clients do it

DBeaver, DataGrip, MySQL Workbench and pgAdmin don't share a small pool across features. They give work its own connection by purpose: one per editor tab or console, one for metadata, and a separate one for dumps and restores (Workbench runs mysqldump as its own process). None of them has a "pool exhausted" error, and none shows an internal connection count. The only connection list they show is the server's process list.

Plan

A central ConnectionManager that hands out connections by purpose (a "lane"), in steps:

Step 1: separate lanes for the agent and for long-running jobs (this issue's first PR)

  • Interactive lane: the existing pool, used by the editor, schema browsing and admin. It's unchanged and still sized by the profile's "Max pool size".
  • Agent lane: its own small pool, used by MCP run, run_ddl, stage_write and the agent's schema reads. A busy or runaway agent can only exhaust its own lane.
  • Job lane: its own small pool for backups and restores, so a long dump never takes a slot the editor needs.
  • The job and agent lanes open lazily and close when idle, so a profile that never uses them costs nothing extra on the server.
  • Cancel stays unified: the Cancel button still reaches statements the agent is running, as it does today.
  • The pool-exhausted message names which lane ran out.

Step 2: a connection per editor tab

Real session semantics per tab (SET @var, temp tables, multi-run transactions), removing the per-statement USE prelude. This changes how tabs map to sessions, so it gets its own PR.

Later

  • A connection per agent session rather than one agent lane per profile, completing FR-6.3.2.
  • Revisit the default pool size and the "Max pool size" setting once the interactive lane only carries interactive work.

Relationship to #727

#727 improves the pool-exhausted message by counting in-flight editor queries. Step 1 removes the main ways the interactive pool fills up without editor queries running (agent and backups), which is what made #727's zero-count message misleading. #727's repro test and message wording are still useful on top of this.

Activity

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

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions