Skip to content

fix(undo): peer-mode TT recycle via cluster floor + stalled-cleaner retry at report cadence#56

Merged
sqlrush merged 2 commits into
mainfrom
fix/s3-tt-allocator-cluster-horizon
Jul 15, 2026
Merged

fix(undo): peer-mode TT recycle via cluster floor + stalled-cleaner retry at report cadence#56
sqlrush merged 2 commits into
mainfrom
fix/s3-tt-allocator-cluster-horizon

Conversation

@sqlrush

@sqlrush sqlrush commented Jul 15, 2026

Copy link
Copy Markdown
Owner

What

Two commits closing the S3 verdict class #2 ("TT retention rollover failed" undo segment-pool exhaustion, node0-concentrated):

  1. feat(undo): gate peer-mode TT reuse on cluster horizon — in peer mode the allocator's Pass 2 no longer recycles COMMITTED TT slots against the local ProcArray horizon (which cannot prove remote snapshots do not need the evidence). COMMITTED-to-FREE authority is delegated to the epoch-fenced cluster undo cleaner (its production cluster-floor fold already exists); the allocator consumes the resulting FREE slot through Pass 1. ABORTED stays directly reusable (invisible to every snapshot); the diagnostic GUC-off bypass also fails closed in peer mode.
  2. fix(undo): retry a stalled cleaner pass at the horizon-report cadence — a recycle pass that cannot prove the cluster floor (missing/stale/epoch/malformed report, member churn, mid-pass epoch fence abort) used to sleep the full cluster.undo_cleaner_interval_ms (30s default) before re-evaluating. The stall causes normally clear within ~one LMON tick (peers re-publish, epoch views converge), so a ~1s transient froze cluster-wide COMMITTED recycling for 30-60s per event — the pool-exhaustion amplifier. A stalled pass now re-arms at Max(lmon interval, 200ms); the interval=0 (pressure-wakeup-only) mode is bounded the same way. Fail-closed unchanged: every retry still recycles ONLY on a proven floor; a persistent cause keeps every retry stalled.

Tests

  • t/402_undo_cleaner_stall_retry_2node.pl (new): pre-fix the heal latency after a cleared stall equals the full cleaner interval (15.1s at a 15s test interval, hard-assert red); post-fix it is the report cadence (1.1s), 14/14. Protection negative leg: with the report-drop kept armed the floor never advances and stall accounting keeps running. Harness note pinned in-test: pg_reload_conf's SIGHUP latch-wakes the cleaner, so the latency measurement uses a single-reload disarm.
  • Unit T48-T50 (allocator peer-mode gating: cleaner-owned recycle, ABORTED direct reuse, GUC-off fail-closed).
  • Gates on the rebased tree (base 52364a4d42): cluster_unit 178/178; TAP t/015 t/017 t/214 t/222 t/270 t/370 t/401 t/402 = 180 asserts; cluster_regress 13/13; PG 219/219; check-format(llvm@18) / comment-headers / scn-cmp / ges-mode / no-clog-overlay all clean.

Spec: spec-5.22e stall semantics (unchanged), spec-3.13 cleaner pass contract.

SqlRush added 2 commits July 15, 2026 13:02
Completion: adds the allocator-side peer-mode guard that prevents direct COMMITTED-slot recycling, keeps ABORTED directly reusable, and adds T48-T50 unit scenarios for cleaner-owned cluster-floor recycle, ABORTED reuse, and GUC-off fail-closed behavior.

Design intent: in peer mode the epoch-fenced cluster undo cleaner is the sole COMMITTED-to-FREE authority after a proven cluster floor; the allocator consumes the resulting FREE slot through Pass 1 instead of trusting a local ProcArray horizon.

Handoff status: this is an unshipped WIP snapshot. No build, unit, integration, or S3 validation was run during this handoff. The peer-report/epoch proof integration, retained-pressure and rollover behavior, and production cleaner call path still require independent evidence; the receiving CC session should evaluate whether to inherit or rework it.
S3 verdict class #2 (25,715 x 'TT retention rollover failed', all on
node0): when the undo cleaner's recycle stage stalls (cluster horizon
unproven: missing/stale/epoch/malformed, member churn, or an F-D2
fence abort), the pass exits and the cleaner sleeps its FULL
cluster.undo_cleaner_interval_ms (30s default) before re-evaluating.
Stall causes normally clear at the horizon-report cadence -- one LMON
tick (1s): epoch views converge and every peer re-publishes -- so a
~1s transient froze cluster-wide COMMITTED recycling for 30-60s.
Field evidence (step-2 rig logs): the boot 'malformed' stall healed
after exactly 60.0s = two passes on all four nodes; the 12:24 'epoch'
stall (blaming a live peer during a dead->alive churn) after exactly
30.0s = one pass.  Under the S3 write storm every reconfig wobble cost
one such freeze; node0 burned the 256-segment pool to the hard cap.

Fix (mechanism, no parameter change): undo_cleaner_run_pass() now
reports whether the recycle stage failed to run against a proven
floor; the main loop then re-arms the next pass at
Max(cluster_lmon_main_loop_interval, 200)ms -- the cadence at which
new reports and epoch convergence can actually arrive -- instead of
the recycle interval.  This also bounds the interval=0 (pressure-
wakeup-only) mode, whose stalled pass previously blocked on a latch
nobody was obliged to set.  Rule 8.A untouched: every retry still
recycles ONLY on a proven cluster floor; a persistent cause keeps
every retry stalled (fold semantics unchanged).

Test: t/402_undo_cleaner_stall_retry_2node.pl.  RED on the pre-fix
binary: heal latency after the stall cause cleared = 15.1s (= the
full 15s test interval); GREEN: 1.1s (report cadence), 14/14.
Protection negative leg: with report-drop KEPT armed the floor never
advances and stall accounting keeps running -- the retry does not
weaken fail-closed.  Harness note: pg_reload_conf's SIGHUP latch-
wakes the cleaner into an immediate pass, so the disarm used for the
latency measurement is single-reload (a two-reload disarm heals the
cleaner by test side effect and masks the cadence under test).

Gates: cluster_unit 177/177; TAP t/214 t/222 t/270 t/370 t/402 (129
asserts); cluster_regress 13/13; PG 219/219; check-format(llvm@18) /
comment-headers / scn-cmp / ges-mode / no-clog-overlay all clean.

Spec: spec-5.22e stall semantics (unchanged); TT lane P1#4.
@sqlrush sqlrush merged commit 6ef83c2 into main Jul 15, 2026
5 checks passed
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