Skip to content

feat(events producer): create initial dipper-producer crate. add initial events proto#648

Closed
cmwhited wants to merge 21 commits into
mainfrom
chris.whited/feat-producer/initial-crate-with-proto
Closed

feat(events producer): create initial dipper-producer crate. add initial events proto#648
cmwhited wants to merge 21 commits into
mainfrom
chris.whited/feat-producer/initial-crate-with-proto

Conversation

@cmwhited

Copy link
Copy Markdown

No description provided.

MoonBoi9001 and others added 10 commits June 22, 2026 16:14
The switch to always-contract-funded agreements removed the SubgraphService
cancel and subgraph-based offer idempotency, but several comments still
described them. Align them and cite the verified collector state bits.
The estimate log printed buffer_multiplier=2.0 next to the result even when the max-addition
ceiling or the floor actually set the limit, so a reader debugging an out-of-gas transaction
assumed 2x headroom never applied. Now logs with_buffer, ceiling, and the bound that won.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
When an indexer accepts the off-chain proposal the agreement stays CREATED until the chain
listener sees on-chain acceptance, but dipper logged this as a CREATED->CREATED transition,
putting a phantom step in anyone's grep of the agreement lifecycle. Log it as a plain event.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The nonce-error warning omitted the nonce that was attempted, so when the signer's cached
counter went stale the failed value was invisible and the gap from chain could not be measured.
The resynced value already appears on the following success line.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
)

Dipper re-checks which indexers should serve each subgraph and creates or cancels agreements to match. A sibling change (#645) will let the worker run these checks concurrently; once it does, two checks for the same request could overlap and each create agreements, over-allocating the request. This adds a short-lived per-request lock — landing first — so the checks can't overlap once concurrency is switched on.
@cmwhited
cmwhited requested a review from MoonBoi9001 June 24, 2026 19:24
@cmwhited
cmwhited force-pushed the chris.whited/feat-producer/initial-crate-with-proto branch from cd0bd84 to f9c598b Compare June 24, 2026 19:51

@MoonBoi9001 MoonBoi9001 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice docs inline text documentation Chris, everything looks good to me. TYVM

// 3. subgraph.indexing.agreement.accepted - Emitted when an Indexer agrees to the indexing request for the Subgraph
// 4. subgraph.indexing.agreement.request.expired - Emitted when an indexer fails to accept within the time limit
// 5. subgraph.indexing.agreement.n_indexers_unavailable - Emitted when selection returns fewer candidates than requested
// 6. subgraph.indexing.agreement.terminated - Emitted if either the Subgraph developer, or Indexer cancel an indexing agreement on a Subgraph.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What if the dipper cancels the agreement on the sg? do we also expose that as an event here?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yeah we probably should. Like subgraph.indexing.agreement.canceled? what data would it have? is it an onchain tx?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We can just use subgraph.indexing.agreement.terminated right? So instead of limiting this to only the Subgraph developer, or Indexer cancelling the agreement, then if the dipper cancels the agreement with an indexer (to pick another indexer instead) then we still expose that here.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Okay perfect. Don't have to change the protobuf then. Thanks 🙏

// Timestamp of when the Indexing Agreement was terminated
uint64 terminated_at = 2;

// 0x address of the entity (developer, indexer, etc) that terminated the agreement

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I see, dipper can just throw his own address here

Base automatically changed from upgrade to main June 25, 2026 11:51
cmwhited and others added 3 commits June 26, 2026 11:05
* fix(reassess): send shortfall event after the chain-time read

The "not enough indexers" event was sent before the step that reads chain time to
stamp deadlines. In local runs that read can fail and retry the whole job, resending
the event each round; sending it after the read makes a retried round emit it once.

* fix(expiration): report proposal time from the deadline clock

The expiry event mixed clocks: "proposed at" came from wall time, "expired at" from
chain time, so with local time controls on, expiry could look earlier than the proposal.
Agreements now stamp proposal time in the deadline's clock; old rows fall back to created_at.
@MoonBoi9001 MoonBoi9001 added the agreement-events Kafka producer for agreement lifecycle events (Studio integration) label Jul 7, 2026
cmwhited and others added 3 commits July 7, 2026 15:07
A recovery sweep running only every 60th poll was the sole emitter of the accepted,
terminated and expired announcements, delaying each by 30 minutes while polling fast and
up to 5 hours once the last live agreement was cancelled. Run those three every poll.
Now that the accepted, terminated and expired announcements sweep every poll, a hung Kafka
broker made each of the 3 sweeps block on its 30-second send, stalling chain polling every
poll. After a failed send the sweeps now back off from 30 seconds up to 300 before retrying.
@cmwhited
cmwhited force-pushed the chris.whited/feat-producer/initial-crate-with-proto branch from 98c254a to b45f5d8 Compare July 14, 2026 22:23
# Conflicts:
#	.release-please-manifest.json
#	CHANGELOG.md
#	bin/dipper-service/src/cancel_dispatch.rs
#	bin/dipper-service/src/chain_client.rs
#	bin/dipper-service/src/chain_client/client.rs
#	bin/dipper-service/src/config.rs
#	bin/dipper-service/src/main.rs
#	bin/dipper-service/src/network/service/chain_listener.rs
#	bin/dipper-service/src/network/service/escrow_reconciler.rs
#	bin/dipper-service/src/network/service/expiration.rs
#	bin/dipper-service/src/network/service/liveness_checker.rs
#	bin/dipper-service/src/network/service/topology.rs
#	bin/dipper-service/src/registry.rs
#	bin/dipper-service/src/worker/context.rs
#	bin/dipper-service/src/worker/handlers/cancel_rejected_agreement_on_chain.rs
#	bin/dipper-service/src/worker/handlers/reassess_indexing_request.rs
#	bin/dipper-service/src/worker/service.rs
#	dipper-pgregistry/src/postgres.rs
#	dipper-pgregistry/tests/it_registry_postgres.rs
#	k8s/deployment.yaml
@cmwhited
cmwhited force-pushed the chris.whited/feat-producer/initial-crate-with-proto branch from b45f5d8 to 4c9d81c Compare July 15, 2026 18:19
@cmwhited

Copy link
Copy Markdown
Author

Closing for #675

@cmwhited cmwhited closed this Jul 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agreement-events Kafka producer for agreement lifecycle events (Studio integration)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants