Skip to content

perf: stop querying the network subgraph on every TAP receipt#1069

Open
MoonBoi9001 wants to merge 6 commits into
mainfrom
mb9/check-rav-redemption-locally
Open

perf: stop querying the network subgraph on every TAP receipt#1069
MoonBoi9001 wants to merge 6 commits into
mainfrom
mb9/check-rav-redemption-locally

Conversation

@MoonBoi9001

Copy link
Copy Markdown
Member

This PR makes the allocation-redeemed receipt check read the indexer's own database instead of issuing a live network-subgraph query per receipt. That lookup sat in the hot path of every paid query: an external round trip (billed, for indexers whose network subgraph is gateway-served) spent asking a question whose answer almost never matters in the routine lifecycle. tap-agent only writes the closing RAV when an allocation ages out of the recently-closed buffer, indexer-agent redeems only closing RAVs, and the eligibility check stops accepting receipts at that same buffer expiry, so by the time a redemption exists, receipts for that allocation are already rejected 1 check earlier. The redeemed check is really insurance against out-of-band redemptions and agent-service config skew, and insurance should not cost a network call per receipt.

The replacement keeps exactly that insurance at zero hot-path cost. indexer-agent already records redemptions in redeemed_at (and reconciles them against the chain in both directions, including clearing on reorg), so the check now holds an in-memory set of redeemed closing RAVs, loaded at startup and updated through a new trigger with pg_notify, the deny-list check's pattern. Rows are scoped to this service provider and keyed by payer, data service, and collection, matching the receipt's own fields.

The TAP receipt path queried the network subgraph once per receipt to ask whether the
allocation's escrow was already redeemed, blocking every paid query on an external round trip.
A watcher now keeps a snapshot for the active allocations and the check reads it in memory.
The redeemed check no longer polls the network subgraph at all. indexer-agent already records
when a collection's closing RAV is redeemed on-chain; the check now loads those rows and stays
current through a trigger with pg_notify, the same pattern the deny-list check uses.
The final flag is only set a finality window after redemption, past the default buffer in
which receipts still pass eligibility, so the check never fired. Keying on last and redeemed_at
fires at redemption time; rows are scoped per service provider and reconnects trigger reloads.
In the routine lifecycle redemption follows the same recently-closed buffer that gates the
eligibility check, so by the time a closing RAV is redeemed, eligibility already rejects the
receipt; the check's real role is insurance against out-of-band redemptions, not a routine gate.
@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for CI Build 29090347846

Coverage increased (+0.1%) to 71.593%

Details

  • Coverage increased (+0.1%) from the base build.
  • Patch coverage: 19 uncovered changes across 1 file (189 of 208 lines covered, 90.87%).
  • No coverage regressions found.

Uncovered Changes

File Changed Covered %
crates/service/src/tap/checks/allocation_redeemed.rs 206 187 90.78%
Total (2 files) 208 189 90.87%

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 15088
Covered Lines: 10802
Line Coverage: 71.59%
Coverage Strength: 111.9 hits per line

💛 - Coveralls

When the notification connection dropped, the watcher reloaded the redeemed set while still
disconnected; sqlx only reconnects on the next receive call, so a redemption landing between
the reload and the reconnect went unseen. Re-issue LISTEN first, then reload, as at startup.
The watcher used to log and skip a notification it could not parse. The payload comes from
this repo's own trigger, so a parse failure means the trigger and the Rust code drifted apart
and every later notification would fail too; reload the whole set from the table instead.
@MoonBoi9001 MoonBoi9001 marked this pull request as ready for review July 10, 2026 14:00
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