Add regression test for subquery materializer multi-chunk log replay (bug 4)#4670
Conversation
…(bug 4) The bug-4 fix (main-log short-circuits in `Materializer.read_history_up_to_subscribed/2`) shipped with #4651 but had no dedicated regression test. This adds a deterministic unit test: with a small `chunk_bytes_threshold` the source shape's persisted main log spans more than one chunk, and startup replay must not re-read (and re-apply) main-log entries it already applied. On the pre-fix naive iteration the test crashes the materializer with `Key ... already exists`; with the fix it replays the full history exactly once. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4670 +/- ##
===========================================
+ Coverage 43.18% 60.04% +16.85%
===========================================
Files 312 395 +83
Lines 25598 43747 +18149
Branches 8699 12581 +3882
===========================================
+ Hits 11054 26266 +15212
- Misses 14466 17403 +2937
Partials 78 78
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
✅ Deploy Preview for electric-next ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Claude Code ReviewSummaryTest-only PR adding a deterministic regression test for bug 4 (subquery materializer re-reading main-log entries when the source shape's main log spans multiple chunks). The production fix already shipped in #4651; this fills the missing coverage gap. Overall: clean, well-targeted, and correct — recommend merge. What's Working Well
Issues FoundCritical (Must Fix)None. Important (Should Fix)None. No changeset is required (test-only, no shipped behavior change) — correctly omitted. Suggestions (Nice to Have)
Issue ConformanceNo GitHub issue is linked, but the PR body references the originating bug triage (#4648, Previous Review StatusResolved since iteration 1: @alco flagged that the test comments narrated "the buggy iteration" (a reverted code state), which reads as noise now that the bug is fixed. The reframe in Still open from iteration 1: only the trivial Review iteration: 2 | 2026-07-02 |
Address review: drop references to "the buggy iteration" (reverted code state) and describe what the test guards in present tense. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
Adds a deterministic regression test for bug 4 from the restore-from-file bug triage in #4648 (bug doc:
packages/sync-service/bugs.md).This is a test-only change. Bug 4's production fix — the two main-log short-circuits in
Materializer.read_history_up_to_subscribed/2— already shipped alongside the bug 1 fix in #4651; it just lacked dedicated regression coverage.Problem (bug 4)
On startup recovery the subquery materializer replays the source shape's persisted history (snapshot + main log) up to its subscribed offset.
Storage.get_log_stream/3returns one chunk per call for the snapshot, but returns the entire requested range for the main log in a single call. When the source shape's main log spans more than one chunk, a replay loop that keeps advancing through chunk boundaries past the first main-log chunk re-reads main-log entries it has already applied. Re-applying aNewRecordfor an existing key raisesKey ... already exists, crashing the materializer (and taking the dependent shape's consumer down with it → 409 must-refetch on the next poll).Solution / coverage
The fix (already merged in #4651) stops iterating as soon as the read steps into the main log. This PR adds the missing regression test:
test/electric/shapes/consumer/materializer_test.exs→"does not re-read main-log entries when the main log spans multiple chunks"chunk_bytes_threshold: 10to force the source shape's main log across ≥2 chunks (asserts the first main-log chunk ends strictly before the subscribed offset).NewRecordinserts in separate main-log chunks, subscribes past both, and asserts startup replay yields the correctvalue_countsexactly once.Test Plan
59 tests, 0 failuresin the file).** (RuntimeError) Key "public"."test_table"/"3" already existsfromread_history_up_to_subscribed/2— confirming it's a genuine failing-first regression test.mix format --check-formattedclean.Notes
An end-to-end variant in
oracle_restore_test.exswas prototyped but not included: it does trigger the crash, but the failure self-heals via a client refetch that re-syncs to the oracle, so it passes with and without the fix — false-confidence coverage. The deterministic unit test is the reliable regression guard.Generated with Claude Code