Concepts · Requests
Request-response is messaging with a return route.
A request is a directed message carrying a request identifier and response address. A response is another message correlated to that request—not an in-process return value.
The request client composes the protocol
The request client:
- Resolves the request destination and a temporary or configured response endpoint.
- Assigns a unique request identifier.
- Adds the response and fault addresses to the outgoing envelope.
- Waits for one of the declared response types or
Fault<TRequest>. - Matches concurrent replies by request identifier.
Consumers respond through the context
An interface consumer can call C# RespondAsync, Java respond, or Kotlin's suspending respond. A handler can instead return its response asynchronously as C# Task<TResponse> / ValueTask<TResponse>, Java CompletableFuture<TResponse> / CompletionStage<TResponse>, or directly from a Kotlin suspending function. MyServiceBus awaits that value and sends it through the same consume-context response path.
Returning a value does not require a context parameter. Add ConsumeContext<TRequest> when the handler needs headers or other receive metadata. A response-bearing method without an incoming response address fails consumption rather than silently discarding the result.
Multiple business responses retain their case
A request may declare two successful protocol outcomes, such as an order status or an order-not-found message. Java exposes nominal records through its sealed Response2; Kotlin projects those cases as a covariant sealed RequestResult so when is exhaustive. Both preserve the declared branch even when response types overlap.
Correlation has distinct identifiers
The response retains the request identifier so the client can match it. Conversation metadata continues across the interaction. A consumed correlation identifier becomes the initiator identifier for follow-up operations; it is not silently reused as the new message's correlation identifier.
A timeout is not a negative response
The default request deadline is 30 seconds. Expiration means the client stopped waiting; the remote operation may still complete. Make non-idempotent operations queryable or use a durable command/event workflow when uncertainty is unacceptable.