Skip to content

refactor: get indexer URLs from the indexing-payments subgraph#669

Merged
MoonBoi9001 merged 8 commits into
mainfrom
mb9/fetch-indexer-urls-from-payments-subgraph
Jul 14, 2026
Merged

refactor: get indexer URLs from the indexing-payments subgraph#669
MoonBoi9001 merged 8 commits into
mainfrom
mb9/fetch-indexer-urls-from-payments-subgraph

Conversation

@MoonBoi9001

@MoonBoi9001 MoonBoi9001 commented Jul 13, 2026

Copy link
Copy Markdown
Member

This PR makes dipper look up indexer URLs in the indexing-payments-subgraph instead of the network-subgraph, and deletes the Graph network subgraph client entirely.

Dipper queried the network subgraph through the gateway to build a full topology of subgraphs, deployments, allocations and operators, but the only data ever read back was the indexer id to URL map. Every other consumer of the network subgraph was removed in earlier PRs. The payments subgraph records each indexer's service URL when it registers with the SubgraphService contract, so the new poller just reads that instead.

2 operator-visible changes:

  • The network config section now takes a single indexing payments subgraph subgraph_endpoint URL plus an optional api_key (the gateway_url and deployment_id keys are gone)
  • An indexer now only becomes resolvable once it registers it's URL with the SubgraphService.

Note the following consequences of this PR:

  • The indexer set changes The old code listed indexers from the network subgraph, which includes anyone registered on the legacy ServiceRegistry or on SubgraphService. The new subgraph only contains indexers that emitted ServiceProviderRegistered on SubgraphService, and only from the deployed subgraph's startBlock onward.

    • The PR assumes that's the right set because DIPs requires SubgraphService registration anyway.
  • Stale URLs never expire. While network subgraph nulls an indexer's URL when it unregisters from the legacy registry; the indexing-payments-subgraph Indexer entity is append-only because SubgraphService has no deregistration event. So the indexer set can only grow, and a departed indexer keeps its dead URL forever.

    • The mitigations are IISA selection, offer expiry, and liveness checking.
  • The operator filter was dropped. The prior solution excluded indexers that had no registered operators and no allocations. While the indexing payments subgraph has no operator data, so that filter is now gone.

  • Snapshot consistency and reorg detection are gone. The old paginated client pinned every page to a single block hash via _meta and detected reorgs by the "no block with that hash found" error. The new fetch pages with a plain id_gt cursor: meaning that pages can come from different blocks, and a reorged registration lingers until the next refresh cycle (60 seconds). The assumption is that a URL map doesn't need point-in-time consistency.

Dipper queried the Graph network subgraph for a full topology of subgraphs, deployments and
allocations, but only ever read indexer URLs out of it. A small poller against the
indexing-payments subgraph (which records each indexer's URL on registration) replaces it.
CI's integration step selects tests named tests::it_ and fails when none match; this branch
deleted the only 2 such tests along with the network subgraph client. New wiremock-backed tests
drive the replacement fetch over HTTP: auth, pagination, invalid entries, and error responses.
The indexers query hardcoded first: 1000 while the pagination loop compared the page length
against a separate PAGE_SIZE constant; editing one without the other would silently stop
pagination after the first page. The query now reads the page size from the same constant.
The startup fetch retried without bound before the admin port opens, so a stalled subgraph
left the pod hanging unready with no restart. Dipper now gives up after 6 attempts and exits,
matching the bounded retry used for the RCA domain fetch.
The refresh loop keeps the previous snapshot when a fetch fails or returns zero indexers, but
only the fetch function had tests. Drive the loop against a mock subgraph to cover the empty,
failing, and successful refresh paths, and drop a needless borrow clippy flagged in this file.
The scheme check used starts_with("http"), which also accepted schemes like httpx://.
A subgraph endpoint answering with 0 indexers (a wrong but well-formed subgraph, say) let
dipper boot with no URLs and then skip every selected indexer with warnings. Startup now
retries on an empty snapshot and exits after 6 attempts, the same as a failing fetch.
Local networks legitimately boot before any indexer has registered, where the non-empty
startup requirement would make dipper exit. With allow_empty_at_startup (default false) set,
dipper boots with a warning and the refresh loop picks up the first registration.
@MoonBoi9001 MoonBoi9001 added the config-migration Config schema changed; update config.json when upgrading past this release label Jul 14, 2026
@MoonBoi9001
MoonBoi9001 merged commit a2217f3 into main Jul 14, 2026
18 of 19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

config-migration Config schema changed; update config.json when upgrading past this release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant