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
## PR Stack
1. [databricks#5135](databricks#5135) — PR 1: scaffold
+ autoscaling targeting + text output
2. [databricks#5136](databricks#5136) — PR 2:
provisioned + JSON/CSV streaming + types
3. [databricks#5138](databricks#5138) — PR 3:
multi-input + multi-statement rejection + error formatting
4. **PR 4 (this PR)** —
[databricks#5143](databricks#5143) — cancellation +
timeout + TUI for >30 rows
Stacked on PR 3.
## Why
PR 3 finished the input ergonomics. The remaining commitments before
this command earns the "experimental" label:
- A long SELECT shouldn't survive Ctrl+C. Today the pgx default closes
the TCP socket but leaves the server-side query running.
- CI scripts want `--timeout` so a single statement can't pin a runner.
- Interactive users with >30 rows benefit from a scrollable browser
instead of a wall of text.
## Changes
**Before:** Ctrl+C tears down TCP but the query runs to completion
server-side. `--timeout` doesn't exist. >30 rows scroll past in the
terminal.
**Now:** Ctrl+C cancels the in-flight query at the server. `--timeout
30s` enforces a per-statement deadline. >30 rows on a TTY open the
libs/tableview viewer.
Specifically:
- **Cancellation watcher.** `buildPgxConfig` now installs
`CancelRequestContextWatcherHandler` with `CancelRequestDelay=0,
DeadlineDelay=5s`. Zero `DeadlineDelay` would race the cancel-request
and could leave the connection unusable; 5s gives the cancel round-trip
time to land.
- **Signal handler.** Per-invocation goroutine watches SIGINT and
SIGTERM. Calls cancel; defer'd stop drains the channel.
- **--timeout flag.** Per-statement `context.WithTimeout` child of the
signal-scoped ctx. `reportCancellation` distinguishes Ctrl+C ("Query
cancelled."), timeout ("Query timed out after Xs."), and plain query
errors. Returns `(msg, invocationScoped)` so the multi-input loop can
drop the source prefix on user-cancel.
- **TUI for >30 rows.** `textSink` now has an `interactive` mode;
`runQuery` enables it when stdout is a prompt-capable TTY. Static
tabwriter table for small results and pipes; libs/tableview for big
interactive ones. If `tableview.Run` fails (TUI startup, terminal resize
race) the sink falls through to the static tabwriter path so the user
still sees the rows.
Integration tests aren't included: aitools (the other experimental
command) doesn't have them either. Acceptance + unit tests cover
argument validation, targeting resolution (SDK-mocked), and output
shapes; cancellation/timeout are unit-tested via the seam in
`cancel_test.go`. Real-wire integration tests are the right addition
when this command graduates from experimental.
## Test plan
- [x] `go test ./experimental/postgres/...` (cancel/timeout/signal
helpers, race-precedence pinning)
- [x] `go test ./acceptance -run
TestAccept/cmd/(psql|experimental/postgres)` (no regressions)
- [x] `go tool ... golangci-lint run ./experimental/postgres/...` (0
issues)
- [x] Manual: Ctrl+C during `SELECT pg_sleep(60)` cancels the
server-side query within ~5s. (Smoked on
`chatbot-lakebase-dev-simon-faltum` (e2-dogfood): SIGINT to `SELECT
pg_sleep(60)` exited the client in 0.53s with `Error: Query cancelled.`;
subsequent `pg_stat_activity` query returned zero rows.)
0 commit comments