Skip to content

test: poll Horizon instead of asserting immediately in clawback tests - #2698

Open
Galmanus wants to merge 1 commit into
stellar:mainfrom
Galmanus:fix/2689-poll-horizon-in-clawback-tests
Open

test: poll Horizon instead of asserting immediately in clawback tests#2698
Galmanus wants to merge 1 commit into
stellar:mainfrom
Galmanus:fix/2689-poll-horizon-in-clawback-tests

Conversation

@Galmanus

Copy link
Copy Markdown

What

Adds a shared poll_horizon_until helper (200ms interval, ~30s cap) to the integration test utils and uses it in the two tests that read Horizon immediately after a CLI submit:

  • tx::clawback::clawback — asserted the post-clawback balance from a single read; on a slow runner it observed the pre-clawback balance (a recurring macOS failure on main).
  • tx::claimable_balance::clawback_claimable_balance — fetched the balance id from a single read; when no record was ingested yet it panicked.

On timeout the helper returns the last observed value, so a genuine failure still shows what Horizon actually reported rather than a bare miss.

Why

Contributes to #2689: these are two of the recurring failure modes in rpc-tests.yml. The race is real — the CLI returns on the RPC acknowledgment, while Horizon ingestion lags behind it. This intentionally does not claim to fix #2689: the dominant ledger_fetch failures since 08-18 are a separate, deterministic issue (the quickstart image now emits ContractEvent's discriminant as type in XDR-JSON while the pinned stellar-xdr 27 expects type_; stellar-xdr 28 fixes it but stellar-rpc-client 28 is unreleased), and retry/quarantine CI policy is a maintainer call.

Note: current CI red on main is pre-existing (ledger_fetch) and unrelated to this change.

Testing

Test-only change; cargo check -p soroban-test --features it --tests and cargo fmt --check clean locally. The behavior change is only exercisable in CI's quickstart environment — which is the point: it removes the ingestion race those runs keep hitting.

Two recurring rpc-tests failure modes come from the same race: the CLI
returns on the RPC acknowledgment, but Horizon ingestion lags behind it,
so a read issued immediately afterwards can observe stale state.

- `tx::clawback::clawback` read the holder's balance once right after the
  clawback and asserted 500 USDC; on a slow runner it saw the
  pre-clawback balance.
- `tx::claimable_balance::clawback_claimable_balance` fetched the balance
  id once right after creating it and panicked when no record existed yet.

Both now poll through a shared `poll_horizon_until` helper (200ms
interval, ~30s cap) that on timeout returns the last observed value, so a
real failure still shows what Horizon reported instead of a bare miss.

Contributes to stellar#2689 (the ledger-fetch failures tracked there are a
separate, deterministic XDR-JSON decode issue).
Copilot AI balanced review requested due to automatic review settings August 22, 2026 10:50
@github-project-automation github-project-automation Bot moved this to Backlog (Not Ready) in DevX Aug 22, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds bounded Horizon polling to reduce integration-test races after CLI transaction submission.

Changes:

  • Adds a reusable Horizon polling helper.
  • Polls for updated clawback balances.
  • Polls for claimable-balance creation before clawback.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
integration/util.rs Adds the shared polling helper.
tx/clawback.rs Polls until the expected balance appears.
tx/claimable_balance.rs Polls until the balance ID appears.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +28 to +42
let mut last = None;
for _ in 0..150 {
if let Ok(response) = reqwest::get(url).await {
if let Ok(json) = response.json::<serde_json::Value>().await {
if let Some(value) = extract(&json) {
if accept(&value) {
return Some(value);
}
last = Some(value);
}
}
}
tokio::time::sleep(std::time::Duration::from_millis(200)).await;
}
last
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog (Not Ready)

Development

Successfully merging this pull request may close these issues.

rpc-tests.yml is chronically flaky on main

2 participants