Skip to content

feat: pg_replication_slots + pg_stat_replication_slots screen (hotkey o)#140

Merged
lesovsky merged 15 commits into
masterfrom
feature/replication-slots
Jun 21, 2026
Merged

feat: pg_replication_slots + pg_stat_replication_slots screen (hotkey o)#140
lesovsky merged 15 commits into
masterfrom
feature/replication-slots

Conversation

@lesovsky

Copy link
Copy Markdown
Owner

Summary

New multi-row pgcenter top screen replslots (hotkey o) showing one row per PostgreSQL replication slot, for disk-fill / WAL-retention incident triage. Feature 005 of the 0.11.0 release.

Hybrid source: pg_replication_slots LEFT JOIN pg_stat_replication_slots ON slot_name — covers all slots (physical + logical). State columns are absolute, the eight logical-decoding counters are per-interval deltas.

15 columns, single query for PG 14–18 (stable subset, no version branching):

slot_name │ slot_type │ active │ wal_status │ retained,KiB │ safe,KiB │
spill_txns │ spill_count │ spill,KiB │ stream_txns │ stream_count │ stream,KiB │
total_txns │ total,KiB │ stats_age

Key decisions

  • retained,KiB = recovery-aware WalFunction(current/receive lsn, restart_lsn) — primary vs standby handled by existing template machinery.
  • Default sort by retained,KiB desc (OrderKey=4) — greediest slot on top (deviates from the col-0 default; intentional).
  • coalesce(...,0) on the 8 diffed counters — physical slots are absent from pg_stat_replication_slots; without it the diff path hits ParseInt(""). Physical slots render 0.
  • NotRecordable (TUI-only in 0.11.0) — record/report is the planned next phase.
  • conflicting/invalidation_reason and pg_stat_subscription_stats deliberately out of scope (documented).

Tests — verified live on PG 14/15/16/17/18

  • Unit: selector (Ncols=15, DiffIntvl=[6,13]) identical across PG 14–18.
  • Tier-1: live FieldDescriptions()==15 schema gate.
  • Tier-2: real physical slot — retained non-NULL, 8 counters render 0 (coalesce).
  • Tier-3: real logical slot via test_decoding — needs wal_level=logical (test image bumped 0.0.9→0.0.10); skips gracefully otherwise.

Touched

internal/query/replication_slots.go (+test), internal/view/view.go (+test), top/keybindings.go, top/help.go, record/record_test.go (NotRecordable count), testing/ + workflows (test-image 0.0.10), deployment.md. Full SDD artifacts under docs/features/005-feat-replication-slots/.

🤖 Generated with Claude Code

lesovsky and others added 15 commits June 21, 2026 14:33
New single-row TUI screen combining pg_stat_bgwriter + pg_stat_checkpointer (PG14-18), hotkey b, TUI-only (NotRecordable). First feature of release 0.11.0. Full SDD trail archived under docs/features/archive/004-feat-bgwriter-checkpointer/.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rals, idempotent test slots, alternatives in decisions

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… hint in task-05

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…age bump (task-04)

- internal/query/replication_slots.go: PgStatReplicationSlots hybrid query
  (pg_replication_slots LEFT JOIN pg_stat_replication_slots) + selector
  SelectStatReplicationSlotsQuery returning (query, 15, [2]int{6,13}); coalesce(0)
  on the 8 diffed counters; recovery-aware retained WAL via WalFunction template.
- internal/query/replication_slots_test.go: selector unit test (Ncols/DiffIntvl,
  PG 14-18) + tier-1 integration schema gate (FieldDescriptions==15).
- testing/: wal_level=logical (test-only) + pgcenter-testing image bump 0.0.9->0.0.10.
- workflows + deployment.md: test-container tag 0.0.10.

Reviews: code/test (task-01) approved; deploy/code (task-04) approved after deployment.md sync.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ical integration tests (task-05)

- internal/view/view.go: register 'replslots' multi-row view (Ncols 15, DiffIntvl [6,13],
  OrderKey 4 = retained desc, NotRecordable) + Configure() case; hotkey 'o' (keybindings.go);
  help mode line gains 'o' (help.go).
- internal/view/view_test.go: TestNew 23->24, TestView_VersionOK PG14 23->24, TestNew_ReplslotsView.
- internal/query/replication_slots_test.go: tier-2 physical-slot + tier-3 logical-slot live
  integration tests (idempotent drop-if-exists, parameterized $1, t.Skipf when wal_level!=logical
  or test_decoding absent).

Reviews: code task-02 approved (0 findings); test/code task-05 passed/approved, slot-name $1
binding + assertion hardening applied.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… replslots view (task-03)

replslots is NotRecordable=true, dropped by filterViews on every version before the
version gate, so wantN +1 on all six rows {7,1,4,7,9,9}->{8,2,5,8,10,10}; wantV unchanged.
Comment block refreshed to document the replslots contribution alongside bgwriter.
Verified: Test_filterViews + 3 adjacent NotRecordable tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…G 14-18

QA gate: build/lint green; vuln green in CI (Go 1.25.11; local-only pre-existing
GO-2026-5037). Full test matrix run against live PG 14-18 containers:
unit + tier-1 (schema gate) + tier-2 (physical slot, coalesce) + tier-3 (logical
slot with wal_level=logical, test_decoding) — all PASS. test_decoding confirmed
shipped in PGDG packages. All acceptance criteria met.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The single mode line overflowed after adding 'o'; descriptions wrapped awkwardly.
Now: 'a,b,f,o' / 'r,w' / 's,t,i' on separate rows, description column aligned with
the rest of the general-actions block.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…h debt, roadmap, metrics; archive

- project-knowledge: overview/architecture/patterns gain the replslots multi-row hybrid view
  (coalesce-for-LEFT-JOIN-NULL + recovery-aware WAL patterns).
- features-catalog: [005] entry. decisions-log: 5 ADRs (hybrid source, coalesce, single-query,
  OrderKey=4 deviation, test-image wal_level=logical). tech-debt: [006] standby retained path
  unverified. roadmap-0.11.0: [005] marked done, next [006] pg_stat_io.
- user-spec: Post-implementation section (matches spec; help-line split + live PG 14-18 verify).
- metrics finalized + copied to docs/metrics/. Feature dir archived.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@lesovsky lesovsky merged commit 50bb2f2 into master Jun 21, 2026
1 check passed
@lesovsky lesovsky deleted the feature/replication-slots branch June 21, 2026 11:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant