Skip to content

rig: drive several RPZ upstreams at once, with churn - #208

Open
johanix wants to merge 1 commit into
johani/rig/ixfr-equivalence-v2from
johani/rig/multi-upstream-churn
Open

rig: drive several RPZ upstreams at once, with churn#208
johanix wants to merge 1 commit into
johani/rig/ixfr-equivalence-v2from
johani/rig/multi-upstream-churn

Conversation

@johanix

@johanix johanix commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Rig only — two new files, no pop code. Stacked on #207, which it uses (IXFR, ApplyIXFR, ZoneBody) and depends on; #207 in turn needs #206. GitHub will retarget this to main automatically once #207 lands.

Why

pop's job is to merge several feeds into one zone with the conflicts resolved. A single upstream tests the transport but not the point, and every rig test so far has used exactly one.

The tests, in increasing order of what they can catch

Two upstreams are merged into the union.

A name carried by both upstreams survives removal from one. This is the case a single feed cannot produce: the removal is genuine for the source that dropped it, but the name is still denylisted elsewhere, so the served zone must not change at all — and it must disappear only when the last source carrying it lets go. pop gets both directions right.

Sustained churn across three upstreams, converging after every round, and then the IXFR chain from before the churn must rebuild exactly what AXFR serves at the end:

churn: serial 2 -> 13, 12 records now
chain: 11 deltas, ending at serial 13

Both halves are needed. Convergence alone says the full-zone view is right; the chain check says a downstream that saw nothing but deltas ends up in the same place. Churn from several sources at once is where those two could plausibly diverge.

A burst of 40 changes with no pause, then 20 more on top of an unsettled state, so several land between one poll and the next and sources change while pop is mid-transfer on another. The claim is only that nothing is lost, not that anything is fast.

Harness decisions

Seeded, and every operation is recorded and replayed into the test log on failure. These bugs depend on the order adds and removals interleave across sources; "it failed once" without the sequence is nearly useless.

Expected state is read back from the feeds, not tracked in a parallel model. A model maintained alongside them can drift from what was actually published, and then the test is checking the model against itself.

Comparisons are exact, not subset. A name that should have gone away but did not is precisely what this is hunting; a "contains" check would sail straight past it.

Verification

All pass, including under -race, and three consecutive runs with no flakiness. Full suite green.

pop's job is to merge several feeds into one zone with the conflicts resolved,
so a single upstream tests the transport but not the point. Four tests, in
increasing order of how much they can catch:

  - two upstreams with distinct names are merged into the union;

  - a name carried by BOTH upstreams survives being dropped from one, and goes
    away only when the last source carrying it drops it. This is the case a
    single feed cannot produce: the removal is real for the source that dropped
    it, while the served zone must not change at all;

  - sustained churn across three upstreams, converging after every round, and
    then the IXFR chain from before the churn must rebuild exactly what AXFR
    serves at the end. Convergence alone only says the full-zone view is right;
    the chain check says a downstream that saw nothing but deltas ends up in
    the same place, and churn from several sources at once is where those two
    could plausibly diverge;

  - a burst of 40 changes with no pause, then 20 more on top of an unsettled
    state, so several land between one poll and the next and sources change
    while pop is mid-transfer on another. The claim is only that nothing is
    LOST, not that anything is fast.

The churn driver is seeded and records every operation, replayed into the test
log on failure. These bugs depend on the order adds and removals interleave
across sources, so "it failed once" without the sequence is nearly useless.

Expected state is read back from the feeds rather than tracked in parallel: a
model maintained alongside them can drift from what was actually published, and
then the test is checking the model against itself.

Comparisons are exact, not subset. A name that should have gone away but did
not is precisely what this is looking for.

All pass, including under -race, and repeatedly.
@johanix
johanix requested a review from a team as a code owner August 24, 2026 16:32
@coderabbitai

coderabbitai Bot commented Aug 24, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e1a55c64-a26e-4235-9e78-2ddfaf784dc4

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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