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
{{ message }}
Repository navigation
Commit c3291f6
Browse filesBrowse the repository at this point in the historyBrowse files
Seam repair walks newest-first and stops at the first failed range (#4186 round-3 H1)
A seam wider than one start's repair cap, or with two or more ranges, could
move the successor's floor past a still-unrepaired seam bucket: oldest-first
capping and repair let the OLDEST buckets close first, which drags the
floor (a bare min(bucket)) down to them even while newer seam buckets in
between stay holes, and RetentionArmSafetySql's probe stops looking above
the new floor. The raw purge could then arm and drop rows neither rollup
ever held.
Fix: the seam window's holes are now scanned, capped and walked separately
from the ordinary window's. The seam takes its cap from the newest end
(closest to the successor's floor) and walks descending; the ordinary
window is unchanged (oldest-first, same cap, same continue-past-a-remainder
handling, since an interior repair can never move the floor). The seam
walk stops at the first range that throws (propagates to the existing
per-target catch) or leaves buckets standing (remaining > 0) rather than
moving on to an older range. Both windows share one cap budget per
aggregate per start, seam first, so "a start never re-materializes more
for one aggregate than an ordinary policy run does" stays true.
CapMaterializationHoleRepairs gains a newestFirst parameter (default
false, unchanged behavior) that also splits a straddling range at its
older edge instead of its newer one, so the kept portion stays adjacent
to whatever is already materialized.
Also corrects RetentionArmSafetySql's doc: it claimed an over-horizon seam
"still gets repaired" and the gate "releases automatically, with no manual
step" unconditionally. Both are true only when the raw purge was already
held when the store stopped (#4299) and the outage did not cross the
upgrade (#4300) respectively. Adds the H2-parity note: the stitch trusts
the frozen legacy's own span without checking it, which can read Covered
over a pre-upgrade hole nothing here repairs -- accepted because 3.8.0
loses the same rows on the same schedule, and the A6 backfill
(--backfill-rollups) covers it for an operator who runs it.
Two live tests against a real TimescaleDB rig:
- a 35-bucket seam (over the 24-bucket cap) stays Short after one walk
(top 24 repaired, bottom 11 still a hole) and reads Covered only after
a second walk closes the rest; revert-proved by temporarily restoring
oldest-first, which fails at the same assertion.
- a two-range seam where the newer range's refresh is forced to raise
23514 via a CHECK constraint on its own materialization chunk: the
older range is never touched and the gate still reads not-safe.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TszxYhJJbTEh4LrZ56NYo3
$"ALTER TABLE {chunks[0]} ADD CONSTRAINT seam2_block_b CHECK (bucket NOT BETWEEN '{u.AddHours(-5):O}'::timestamp AND '{u.AddHours(-4):O}'::timestamp)",
Assert.True(summary.Failures>=1,$"expected B's constraint violation to be caught as a failure, got {summary.Failures}");
805
+
806
+
/* A is untouched: no row near it exists in the successor at all. */
807
+
awaitusing(varprobeA=newNpgsqlCommand(
808
+
$"SELECT count(*) FROM collect.{TimescaleSupport.ProcedureStatsIntervalHourlyView} WHERE bucket >= '{s.AddHours(-19):O}'::timestamp AND bucket < '{s.AddHours(-17):O}'::timestamp",
0 commit comments