Skip to content

feat: add configurable retries for emitters - #658

Open
kahirokunn wants to merge 6 commits into
cloudevents:mainfrom
kahirokunn:split/emitter-retry
Open

kahirokunn wants to merge 6 commits into
cloudevents:mainfrom
kahirokunn:split/emitter-retry

Conversation

@kahirokunn

Copy link
Copy Markdown
Contributor

Proposed Changes

Add opt-in retries with withRetry().

Description

Retry temporary HTTP and network failures with capped randomized exponential backoff, honoring Retry-After for 429 and 503 responses. Each attempt sends the same CloudEvent, so receivers need to handle duplicates.

Depends on #657.

Signed-off-by: kahirokunn <okinakahiro@gmail.com>
Signed-off-by: kahirokunn <okinakahiro@gmail.com>
Use the platform HTTP client in Node.js and browsers without importing
Node-only http and https modules into the SDK's public entry point.
Preserve CloudEvent serialization, URL credentials and per-send headers,
and expose transport-wide headers and Fetch request options.

Keep the transport result inferred through emitterFor(). HTTP status codes
still resolve at this point; delivery failure handling is a separate change.

BREAKING CHANGE: httpTransport() resolves with { response, body }, where
response is the native Fetch Response, instead of { body, headers }.
Node.js global HTTP agents no longer configure these requests; a Fetch
dispatcher configures proxies, client certificates and custom trust.

Signed-off-by: kahirokunn <okinakahiro@gmail.com>
Reject responses that did not accept the event and distinguish HTTP status
failures from requests that never produced a response. Keep an unreadable
body after a successful status separate from a failed delivery, so a caller
does not resend an event the receiver has already accepted.

Allow transport-wide and per-send response handlers, preserving their body
types through emitterFor(). Include text and discard handlers and clean up
the body after a handler fails.

BREAKING CHANGE: non-2xx HTTP responses reject with HTTPTransportError.
Successful responses resolve with either body or bodyError. Options.headers
is checked by TypeScript, and built-in HTTP transport annotations use
HTTPTransportFunction and HTTPEmitterFunction.

Signed-off-by: kahirokunn <okinakahiro@gmail.com>
Combine transport-wide and per-send abort signals while fetching and
handling a response. Preserve the first abort reason, support signals from
another realm and detach subscriptions when the operation finishes.

Keep the shared signal implementation in its final module so emitter
wrappers can reuse it without moving transport code in a later feature.

BREAKING CHANGE: Options.signal is checked as an AbortSignal. A cancelled
HTTP request rejects with HTTPTransportError of kind aborted; a body
failure after a successful status remains a successful delivery result.

Signed-off-by: kahirokunn <okinakahiro@gmail.com>
Keep the HTTP transport single-attempt and let applications opt into
retrying temporary failures with a reusable emitter wrapper. Preserve
the event and send options across attempts, bound backoff waits and honor
Retry-After for 429 and 503 responses.

Default retries recognize temporary HTTP failures, while custom transports
can supply their own predicate and delay. Aborted sends are not retried,
and a per-send signal can interrupt the wait before another attempt.

Signed-off-by: kahirokunn <okinakahiro@gmail.com>
@kahirokunn
kahirokunn marked this pull request as ready for review October 13, 2026 12:28

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