Skip to content

test: stop test_topics_filter_pulse_still_ticks flaking on interleaved pulse ticks - #148

Merged
cablehead merged 1 commit into
mainfrom
fix-pulse-flake
Aug 6, 2026
Merged

test: stop test_topics_filter_pulse_still_ticks flaking on interleaved pulse ticks#148
cablehead merged 1 commit into
mainfrom
fix-pulse-flake

Conversation

@cablehead

Copy link
Copy Markdown
Owner

What flaked and why

test_topics_filter_pulse_still_ticks failed on the windows and macos CI runners while passing on ubuntu and local Linux.

The actor under test is configured with pulse: 50, so it emits a filter.out frame with tick: true every 50ms. The test consumed the first tick, then appended noise and ev and asserted the recv order was exactly noise then ev:

store.append(Frame::builder("noise").build()).unwrap();
store.append(Frame::builder("ev").build()).unwrap();
assert_eq!(recver.recv().await.unwrap().topic, "noise"); // got "filter.out" on slow runners
assert_eq!(recver.recv().await.unwrap().topic, "ev");

On a slow runner, more than 50ms passed between consuming the first tick and this recv, so a second pulse tick landed in the store ahead of noise and the strict assert_eq!(... "noise") got filter.out instead. The actor is behaving correctly: async pulse ticks interleave with data frames, and the order between a tick and a data frame is not guaranteed. The loop further down already tolerated interleaved ticks; these two asserts did not.

Deterministic repro

Sleep 60ms (past one 50ms pulse period) after consuming the first tick and before appending, so a second tick is always queued ahead of the data frames on any machine. With that in place the old strict asserts fail deterministically (assertion left == right failed, left: "filter.out", right: "noise"), matching CI.

The fix

Keep the forced interleave so the test genuinely exercises the tick-between-data-frames case going forward, and tolerate ticks the same way the loop already did: drain filter.out tick frames, then assert only that noise and ev arrive in append order and the actor's filter.out {seen: ev} output arrives.

Verification

  • cargo test: 189 + 12 + 8 passed, 0 failed
  • processor::actor::tests module: 35 passed
  • cargo fmt --check and cargo clippy -- -D warnings: clean
  • nu tests/test_xs_nu.nu: a pre-existing scru128 id-roundtrip failure reproduces on a clean checkout of this branch's base too, unrelated to this change
  • docs/astro step in check.sh needs Node >=22.12.0; the local Node is v18.19.1, so that step is gated by the environment (unrelated to this change)

…d pulse ticks

The actor is configured with pulse 50, so it emits a filter.out tick frame
every 50ms. The test consumed the first tick, then appended "noise" and "ev"
and asserted recv order was exactly "noise" then "ev". On slow windows and
macos CI runners a second tick landed in the store ahead of "noise", so the
recv returned "filter.out" and the strict assert_eq failed. The actor is
correct: async ticks interleave with data frames and the order between them is
not guaranteed. The two asserts over-specified that order.

Force the interleave to make it deterministic: sleep 60ms (past one 50ms pulse
period) after the first tick and before appending, so a second tick is always
queued ahead of the data frames on any machine. Then tolerate ticks the same
way the loop already did: drain filter.out tick frames and assert only that
"noise" and "ev" arrive in append order and the actor's filter.out {seen: ev}
output arrives.
@cablehead
cablehead merged commit 95b9273 into main Aug 6, 2026
10 checks passed
@cablehead
cablehead deleted the fix-pulse-flake branch August 6, 2026 03:04
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