Skip to content

test(ts): fix flaky subscribeToEvents (race + block-time-dependent window)#4059

Merged
Kailai-Wang merged 1 commit into
devfrom
fix/flaky-subscribe-to-events
Jun 30, 2026
Merged

test(ts): fix flaky subscribeToEvents (race + block-time-dependent window)#4059
Kailai-Wang merged 1 commit into
devfrom
fix/flaky-subscribe-to-events

Conversation

@Kailai-Wang

Copy link
Copy Markdown
Collaborator

Problem

The heima zombienet ts-test job has been intermittently failing with:

Error: timed out listening for event omniBridge.PaidIn

(seen on #4057 and #4058, both unrelated to their actual changes — paseo, which runs the same suite, passes). Two root causes in subscribeToEvents:

  1. Subscribe-after-event race. Callers do await executeTransaction(...) — which resolves once the EVM tx is mined — and only then call subscribeToEvents. The helper only watched future subscribeNewHeads, so the event was frequently already in a past block. It then scanned 30 empty blocks and rejected. (Passing at all was luck — subscription registering near the event's block boundary.)
  2. Block-time-dependent window. The budget was a fixed blocksToScan = 30. At 12s that was ~6 min; after the 12s→6s upgrade it silently became ~3 min — so the same test got tighter for no logical reason, making the flake more frequent.

Affected call sites: precompile-contract.test.ts omniBridge.PaidIn and vesting.VestingCompleted (latter merely got lucky).

Fix

subscribeToEvents now:

  1. Looks back over the last LOOKBACK_BLOCKS (10) from the current head and returns immediately if the event already landed — kills the race without touching call sites.
  2. Falls back to a forward watch bounded by wall-clock time (FORWARD_TIMEOUT_MS = 180s) instead of a block count, so the window no longer shrinks with block time.
  3. Adds a settle-once guard so the timeout and the head-watcher can't double-resolve/reject.

No call-site changes required; signature unchanged.

Verification

  • tsc --noEmit clean for the changed file.
  • prettier-formatted.
  • The heima ts-test job exercises both affected events end-to-end in CI.

…ndow)

subscribeToEvents only watched *future* heads for up to 30 blocks. Callers
typically `await` the triggering extrinsic (tx.wait() resolves once mined)
*before* subscribing, so the event is often already in a past block — the
watcher then scans 30 empty blocks and times out. The 30-block budget also
silently halved in wall-clock terms when block time dropped 12s -> 6s, making
the omniBridge.PaidIn / vesting.VestingCompleted assertions flaky in CI.

Scan a window of recent blocks back from the current head first (catches the
already-emitted event), then fall back to a forward watch bounded by wall-clock
time (180s) instead of a fixed block count, so it no longer shrinks with block
time. Settle-once guard avoids double resolve/reject.
@vercel

vercel Bot commented Jun 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
heima-aa-demo-app Ignored Ignored Jun 30, 2026 2:01pm

Request Review

@Kailai-Wang Kailai-Wang merged commit 6f22cf1 into dev Jun 30, 2026
15 checks passed
@Kailai-Wang Kailai-Wang deleted the fix/flaky-subscribe-to-events branch June 30, 2026 14:44
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