Idempotency and delivery outcomes
Repost dedupes on the idempotency key. When you don’t pass one, the runtime generates a stable key per operation and reuses it across that operation’s retries. When you pass one viaSendOptions, reuse the same key to make a send safe to repeat.
Every failure is a RepostException carrying a stable RepostErrorCode, a best-known DeliveryState, the idempotencyKey, the started attemptCount, and an isRetryable() flag — never a raw server body, header, or nested throwable. The five delivery states:
switch: RepostConfigurationException (bad config), RepostValidationException (your model failed validation, NOT_SENT), RepostSerializationException, RepostTransportException (connect/TLS/timeout/cancel/overload), RepostPublishException (the server returned a rejection or a retryable failure), and RepostDescriptorVersionException (regenerate or upgrade — the client and runtime versions are incompatible).
Async and cancellation
createdAsync(...) returns a SendOperation, which is both a CompletionStage<SendResult> and a Future<SendResult>. Cancel it like any Future; the delivery outcome still settles on a separate, non-cancellable stage you read with outcome():
NOT_SENT; cancelling after it may have been written settles CANCELLED_UNKNOWN. Either way the operation settles exactly once and closes only the work it owns.
Bounded admission
maxInFlightOperations is a hard bulkhead, not a queue. When more operations are in flight than the budget allows, a new send is rejected immediately with an OVERLOADED error and NOT_SENT — the runtime never buffers unbounded work or paces your traffic. Treat it as backpressure:
Continue
Observability
Watch in-flight operations, dropped events, and attempt lifecycles.
Testing
Assert on outcomes and recorded requests without the network.
SDKs
The behavior every generated client shares, in every language.