You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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:
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.
A backup occupies a shared slot for its whole run. Add a few schema loads and the editor gets "pool timed out".
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".
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.
#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.
Problem
Every connection profile opens one sqlx pool (default max 5, 10s acquire timeout), and everything shares it:
query/executor.rsschema/inspector.rs(18 call sites)backup/writer.rs,restore/runner.rs, each holding one connection for the whole runmas-adminsrc/mcp/workspace.rs:runandrun_ddlthrough the same executor,stage_writefrom the same pool, holding row locks for up to the staging deadlineConsequences:
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.USE dbbefore 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
mysqldumpas 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
ConnectionManagerthat 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)
run,run_ddl,stage_writeand the agent's schema reads. A busy or runaway agent can only exhaust its own lane.Step 2: a connection per editor tab
Real session semantics per tab (
SET @var, temp tables, multi-run transactions), removing the per-statementUSEprelude. This changes how tabs map to sessions, so it gets its own PR.Later
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.