Skip to content

fix(chip-router): match atlas write-service Publish/PublishBatch semantics - #2873

Draft
pkcll wants to merge 1 commit into
fix/chip-router-per-event-publish-resultsfrom
fix/chip-router-match-write-service
Draft

pkcll wants to merge 1 commit into
fix/chip-router-per-event-publish-resultsfrom
fix/chip-router-match-write-service

Conversation

@pkcll

@pkcll pkcll commented Oct 16, 2026

Copy link
Copy Markdown

Stacked on #2861 — implements the review findings so the chip-router matches the atlas chip-ingress write-service's behavior. Only the delta on top of #2861's head (c69acae) is in this PR's diff.

Changes

Reference: atlas chip-ingress internal/server/server.go / internal/service/write_service.go.

  • Publish (single event) now matches the write-service's all-or-nothing contract. The write-service's single-event RPC delegates to PublishCloudEvents with transaction_enabled=true: any failure returns a gRPC error, success returns exactly one PublishResult. The router previously returned &PublishResponse{}, nil unconditionally — acking events that went nowhere (the data-loss shape fix(chip-router): populate per-event PublishBatch results #2861 fixes for PublishBatch) and returning zero results on success. It now fails when no subscribers are registered, when every forward fails, or when no subscriber accepts the event, and returns one result on success.
  • Failure RPCs use codes.Internal — the write-service's failure code (InternalError = status.Errorf(codes.Internal, "failed to publish events")) — in place of codes.Unavailable across all failure paths. No node-side behavior change (the durable emitter retransmits on any error), but the router now speaks the same failure dialect as the write-service.
  • Empty batch short-circuits to a no-op success before the subscriber check, matching the write-service's empty-batch path (previously: Unavailable with no subscribers).
  • Order-independent detail merge, sized to the batch. detail is now a fixed-length slice indexed by event position: a later subscriber's results can extend detail past the first provider's length (previously trailing events were acked with no detail), acceptance always wins over rejection, and a rejection only fills an empty slot. Also: a detail-less success (empty results, nil error) now accepts the whole batch, clearing other subscribers' rejections — the intent documented in fix(chip-router): populate per-event PublishBatch results #2861's comments but not enforced by its merge (a detail-less success + another subscriber's per-event rejection still reported the event rejected, even though it was delivered).

Tests

go test -count=20 -race ./cmd/chip-router/ — new coverage: single-event success (1 result) / no-subscribers / all-forwards-failed / all-rejected / detail-less acceptance overriding a rejection; empty-batch no-op; merge extension past the first provider's detail; a rejection surviving another subscriber's RPC failure; codes.Internal assertions. Stub simplified to an immutable struct (no mutex/counter).

golangci-lint (repo config): 0 issues.

…ntics

Aligns the router with the atlas chip-ingress write-service, addressing
the review findings on #2861:

- Publish (single event) now follows the write-service's all-or-nothing
  contract (atlas chip-ingress internal/server: Publish delegates to
  PublishCloudEvents with transaction_enabled=true): it fails the RPC
  when no subscribers are registered, when every forward fails, or when
  no subscriber accepts the event, and returns exactly one PublishResult
  on success. Previously it returned an empty PublishResponse with a nil
  error unconditionally, acking events that went nowhere.
- Failure RPCs use codes.Internal, the write-service's failure code, in
  place of codes.Unavailable.
- An empty batch short-circuits to a no-op success before the subscriber
  check, matching the write-service's empty-batch path.
- The per-event detail merge is now order-independent and sized to the
  batch: a later subscriber's results can extend detail beyond the first
  provider's length (previously trailing events were acked with no
  detail), and a detail-less success (empty results, nil error) now
  accepts the whole batch, clearing other subscribers' rejections —
  the intent documented in #2861 but not enforced by its merge.

Tests: single-event success/failure paths, empty batch, detail-less
acceptance, merge extension past the first provider's detail, rejection
surviving another subscriber's RPC failure; stub simplified to an
immutable struct.
@github-actions

Copy link
Copy Markdown

📊 API Diff Results

No changes detected for module github.com/smartcontractkit/chainlink-testing-framework/framework/components/chiprouter

View full report

This branch has not been deployed

No deployments
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