Repository navigation
Optimized inline request/reply over the Wolverine.Http transport (GH-2966) - #2990
Merged
Merged
Conversation
…2966) When InvokeAsync<T> routes to an HTTP transport endpoint, the HTTP response body IS the reply — no ReplyListener, no listener loop on the sender, no cross-loop TaskCompletionSource. Sender: - New IInlineRequestReplyEndpoint capability (Wolverine core). MessageRoute caches `endpoint as IInlineRequestReplyEndpoint` once at construction (routing-compile time) and, when present, RemoteInvokeAsync<T> sends + reads the reply envelope straight back instead of registering a ReplyListener — no per-message branching. - HttpEndpoint implements the capability: serializes the request, POSTs to its OutboundUri, and deserializes the reply envelope from the HTTP response body. - IWolverineHttpTransportClient.InvokeAsync returns (status, body) so a 500 carrying an envelope-shaped error reply is read regardless of status. - A receiver handler failure comes back as a FailureAcknowledgement reply and is rethrown as WolverineRequestReplyException — same caller semantics as brokers. Receiver: - HttpTransportExecutor (the existing /_wolverine/invoke endpoint already runs the handler and writes Envelope.Response to the body) now maps a handler exception to HTTP 500 + a FailureAcknowledgement envelope body. (Uses IntrinsicSerializer.Write, not WriteMessage — the latter intentionally throws.) Auto-activates per-endpoint via the transport capability; no user-facing opt-in. Fire-and-forget HTTP sends are unchanged. Docs added (guide/http/transport.md). Follow-up #2989 tracks full cross-process integration coverage + the CritterWatch HTTP-only control use case. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ng (GH-2966) Replaces the per-call `if (_inlineRequestReply != null)` branch in MessageRoute.RemoteInvokeAsync<T> with polymorphism. The "send the request and resolve the reply" step is now a protected virtual seam (sendAndAwaitReplyAsync<T>); the base keeps the brokered reply-tracker/listener path, and a new InlineReplyMessageRoute overrides it to read the reply straight off the transport response (HTTP). The shape is chosen once at routing-compile time by a new MessageRoute.For(messageType, endpoint, runtime) factory based on whether the endpoint implements IInlineRequestReplyEndpoint, so there is no per-message if/then. All route construction sites now go through MessageRoute.For; the factory is the only place that news up a route, and the selection is behavior-preserving for every non-inline transport. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Member
Author
|
Updated per review: the sender path is now polymorphic instead of a runtime
Verified: the two inline request/reply tests pass, 41 core request/reply + routing tests pass, and Also filed #2994 to spec using the HTTP transport as a Wolverine cluster's node control endpoint (control queue), which builds directly on this inline request/reply work. |
This was referenced May 31, 2026
This was referenced Jun 1, 2026
This was referenced Jul 13, 2026
This was referenced Jul 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2966.
When
IMessageBus.InvokeAsync<T>(message)routes to a Wolverine.Http transport endpoint, the HTTP response body is the reply — noReplyListener, no listener loop on the sender, no cross-loopTaskCompletionSource.Sender
IInlineRequestReplyEndpointcapability (Wolverine core).MessageRoutecachesendpoint as IInlineRequestReplyEndpointonce at construction (routing-compile time); when present,RemoteInvokeAsync<T>sends the request and reads the reply envelope straight back instead of registering aReplyListener— no per-message branching, null for every other transport.HttpEndpointimplements the capability: serializes the request, POSTs to itsOutboundUri, deserializes the reply envelope from the HTTP response body.IWolverineHttpTransportClient.InvokeAsyncreturns(status, body)so a 500 carrying an envelope-shaped error reply is read regardless of status.FailureAcknowledgementreply and is rethrown asWolverineRequestReplyException— identical caller semantics to brokered request/reply.Receiver
The existing
/_wolverine/invokeendpoint already ran the handler and wroteEnvelope.Responseto the body. Now a handler exception maps to HTTP 500 + aFailureAcknowledgementenvelope body (usingIntrinsicSerializer.Write—WriteMessageintentionally throws). Outbox commit already happens (viaInvokeInlineAsync's flush) before the response is written.Design notes
_inlineRequestReplyis null for non-HTTP endpoints).Tests
inline_request_reply_senderdrives the full sender path (InvokeAsync<T>→MessageRouteinline branch →HttpEndpoint→ reply) with a fake transport client standing in for the receiver. The host configures no listening endpoint, so the tests only pass because the reply is read off the response slot (otherwise they'd time out):WolverineRequestReplyException.(Pre-existing unrelated flake noted:
HttpTransportExecutorTests.batch_with_multiple_queues_routes_to_correct_queuefails on cleanmaintoo.)Verification
dotnet build wolverine.slnx -c Releaseclean.Docs & follow-up
guide/http/transport.md.Result<T>composition (Formal support for the stupid Result pattern in "Wolverine as MediatR" usage #2221), and documenting/using this as the control mechanism for CritterWatch against HTTP-only services.🤖 Generated with Claude Code