Every generated send returns a *repost.SendResult or a typed *repost.Error with the runtime's best-known delivery state. Use that state and the idempotency key together when deciding whether to retry or reconcile.
Idempotency and delivery states#
When IdempotencyKey is empty, the runtime creates one key and reuses it across that operation's attempts. Pass your own stable business key when a queue redelivery, process restart, or application retry may repeat the same logical send.
DeliveryState | Meaning | What to do |
|---|---|---|
ACCEPTED | Repost accepted the event. | The send returns SendResult; no reconciliation is needed. |
NOT_SENT | The request definitely did not leave. | Retry with the same key when the error is retryable. |
POSSIBLY_SENT | Repost may have received the request, but the result is unknown. | Reuse the same key and reconcile. Do not mint a new key. |
REJECTED | Repost definitively rejected the request. | Fix the request instead of retrying blindly. |
CANCELLED_UNKNOWN | Cancellation happened after the request may have committed. | Reuse the same key and reconcile. |
Handle typed errors#
result, err := client.Webhooks.Order.Created(ctx, input)
if err != nil {
var failure *repost.Error
if !errors.As(err, &failure) {
return err
}
switch failure.DeliveryState {
case repost.DeliveryStatePossiblySent, repost.DeliveryStateCancelledUnknown:
return reconcile(failure.IdempotencyKey)
case repost.DeliveryStateNotSent:
if repost.IsRetryable(failure) {
return retryLater(failure.IdempotencyKey)
}
}
log.Printf("send failed: category=%s code=%s", failure.Category(), failure.Code)
return failure
}
use(result)Error contains stable fields for Code, DeliveryState, Retryable, AttemptCount, IdempotencyKey, HTTPStatus, and FailureReason. Validation and configuration failures also expose bounded issue lists. Category() groups codes by configuration, validation, serialization, transport, publish, or descriptor-version remediation.
Error strings and structured logging exclude credentials, payloads, response bodies, URLs, headers, and raw cause text. Log stable fields from Error; do not log the original event to diagnose a send.
Retry behavior#
The runtime owns retries for the built-in HTTP transport and custom transports. A transport performs exactly one attempt.
Retry candidates include classified DNS, connection, I/O, and attempt-timeout failures; 409, 429, and 5xx responses; and malformed successful responses when delivery may already have occurred. TLS verification failures, proxy authentication failures, redirects, and ordinary non-retryable 4xx responses are terminal.
The default is four total attempts. Backoff uses full jitter from zero through the exponential cap. Valid Retry-After delta-seconds and HTTP-date values can raise the delay, but never beyond 60 seconds or the remaining operation time.
Deadlines and cancellation#
The earlier of the caller's context deadline and OperationTimeout bounds attempts and retry delays together. AttemptTimeout bounds one HTTP attempt; ConnectTimeout bounds connection establishment.
Pass the request or job context to the generated method:
ctx, cancel := context.WithTimeout(parent, 10*time.Second)
defer cancel()
result, err := client.Webhooks.Order.Created(ctx, input)Cancellation before request bytes may have left settles as NOT_SENT. Cancellation after commit settles as CANCELLED_UNKNOWN. The generated method returns only after the operation has released its runtime reservations and chosen a delivery state.
Bounded admission#
MaxInFlightOperations is a hard process-level bulkhead, not a queue. MaxBufferedBytes bounds aggregate request, response, and parsing storage. When either budget is full, a new operation fails immediately with OVERLOADED and NOT_SENT before credentials, serialization, clocks, or transport work.
Apply backpressure in your job queue or request handler, then retry with the same idempotency key. Increasing the limits also increases the maximum memory and connection pressure one process can create.
Wire behavior#
The runtime sends type, customerId, timestamp, and data in that order. Payload fields follow schema declaration order and use their @map wire names. Absent optional values are omitted, explicit nulls are preserved when allowed, and schema defaults are injected only for absent fields.
The generated client, runtime, default Go transport, and response parser are exercised together over real local HTTP/1.1 and HTTP/2 sockets in the native Go suite.