WolverineFx.Http.Grpc — gRPC Support for Wolverine HTTP Endpoints#2281
WolverineFx.Http.Grpc — gRPC Support for Wolverine HTTP Endpoints#2281erikshafer wants to merge 49 commits intoJasperFx:mainfrom
Conversation
Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
…ing in docs Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
… design decisions Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
…, updated tests Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
…ct proto-first support Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
…test Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
…ing docs Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
… entries - Replace all 'ASP.NET Core' with 'ASP.Net Core' to match Wolverine convention - Rename 'Option A/B/C' service class alternatives to descriptive names (convention-based, attribute-based, attribute + constructor injection) - Rename 'Add a gRPC endpoint adapter' step to 'Write the gRPC service class' - Fix empty first-column header in code-first vs proto-first comparison table - Replace bare path strings with GitHub hyperlinks for all three sample projects - Rename 'Roadmap' section to 'Design Notes' (more appropriate for a docs page) - Tighten intro prose in Code-First Approach section (one sentence, not two) - Add PingPongWithGrpc, ProtoFirstGrpcSample, RacerGrpcSample to samples.md" Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
…ces) Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
… (code-first pattern, no constructor needed) Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
… contributors - Reduced verbosity in XML documentation throughout Wolverine.Http.Grpc - Simplified class/method summaries while retaining essential information - Streamlined comments in GrpcEndpointSource, WolverineGrpcExtensions, and base classes - Made sample code comments more concise without losing educational value - Condensed test documentation to focus on key testing scenarios - Maintained important context (e.g., why WebApplication vs AlbaHost) while removing repetition - All 29 tests pass successfully after refactoring Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
…ely in cleanup commit Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
- Add end_to_end_grpc_integration.cs with actual gRPC network call tests - Add message_bus_integration.cs for Bus.InvokeAsync/PublishAsync/SendAsync tests - Add dependency_injection_and_services.cs for DI patterns (property vs constructor) - Add error_handling_and_exceptions.cs for exception propagation tests These new tests mirror patterns from Wolverine.Http.Tests and provide: - Real gRPC client-server integration tests (not just route registration) - Message bus operation verification - Service resolution and DI pattern validation - Error handling and exception propagation Note: New end-to-end tests require HTTP/2 Kestrel configuration to run. Existing unit tests (type discovery, bootstrapping) all pass (29 tests). Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
…erns and conventions Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
…traints and gotchas Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
- Configure Kestrel to use HTTP/2 via IPAddress.Loopback - Fix abstract type discovery to exclude WolverineGrpcEndpointBase descendants - Enable handler discovery for message bus integration tests - 38 of 44 tests now passing (9 more than before) - Verified proto-first and code-first samples work correctly Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
Add code gen, add explicit proto-first gRPC docs in FAQ, update samples
|
March-12-2026: Added code generation capabilities 🎉
|
- Add OpenTelemetry tracing constants and helpers for streaming operations to WolverineTracing - Add StreamingTelemetryExtensions.WithTelemetry() for instrumenting gRPC streams - Add IMessageBus.StreamAsync<TResponse>() API (placeholder for future full implementation) - Streaming telemetry tracks start, message yields, completion, errors, and metrics Benefits: - gRPC streaming operations can now be traced with OpenTelemetry - Lays groundwork for full streaming middleware pipeline integration - Provides observability into stream duration, message counts, and errors Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
Add test suite for StreamingTelemetryExtensions.WithTelemetry(): - Verify streaming activity creation and tagging - Test message count and duration metrics - Validate error handling and status codes - Test correlation ID propagation - Verify individual message yield events - Test cancellation token handling All tests pass successfully demonstrating telemetry instrumentation works correctly for gRPC streaming scenarios. Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
Add full handler pipeline support for IAsyncEnumerable<T> streaming: - Extend IMessageInvoker interface with StreamAsync<TResponse> method - Implement streaming execution in Executor class with telemetry - Update MessageBus.StreamAsync to invoke handlers instead of throwing - Add streaming support stubs to routing classes (MessageRoute, TopicRouting) - Update NulloMessageInvoker implementations for consistency - Add comprehensive streaming handler tests in CoreTests This allows handlers to return IAsyncEnumerable<T> and be invoked via IMessageBus.StreamAsync, with proper OpenTelemetry instrumentation. Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
- Fix compilation errors in StreamingHandlerTests.cs (CountRequest record syntax) - Add streaming_invoker_behavior_tests.cs with edge cases: * Handler returns IAsyncEnumerable stream * Handler returns empty stream * Handler throws exception after yielding items * Streaming respects cancellation tokens * Null message throws ArgumentNullException * Multiple consumers can call streaming handlers Tests validate Executor.StreamAsync behavior through IMessageBus.StreamAsync API. Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
…amAsync integration Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
…treamAsync pattern Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
…ve NullReferenceException Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
…erine-again' into copilot/add-grpc-support-to-wolverine-again
…oard, now using primary constructor
Co-authored-by: erikshafer <12145838+erikshafer@users.noreply.github.com>
|
Given that we've recently asked ourselves the question whether we could also use Wolverine for our gRPC api endpoints this is a welcome addition. Any clue on when it might be ready? |
Hi @Blackclaws ! I will be refreshing this effort tomorrow, actually. @jeremydmiller recently asked what the status was and I just need a little bit more time before I got back into this. Will be tweaking a few things, along with a much-needed rebase from the |
A new PR and git branch will be posted shortly. Closing this PR. Apologies for the madness! |
Add gRPC Support and Streaming Handler Capabilities to Wolverine
This PR adds comprehensive gRPC support to Wolverine, enabling both code-first (protobuf-net.Grpc) and proto-first (.proto files + Grpc.Tools) approaches for building gRPC services with Wolverine's handler pipeline. Additionally, it implements streaming handler support with OpenTelemetry instrumentation for the core Wolverine message bus.
What's Included
1. gRPC Code Generation (Added March 12, 2026)
GrpcChain: New code generation chain that implementsICodeFilefor generating service wrappersHow it works:
2. Streaming Handler Support ✨ NEW
Implemented streaming handler support with comprehensive telemetry integration:
Message Bus Streaming API (Commits 296b09b, 91e6554, 7aa7cb0, 7629b3f) ✅ Complete
IMessageBus.StreamAsync<TResponse>(): New public API for streaming responses from handlersIAsyncEnumerable<T>and Wolverine's pipeline will stream resultsUsage Example:
Implementation Details:
IMessageInvoker: Extended withStreamAsync<TResponse>()methodExecutor: Implements streaming execution path with telemetryMessageBus: Public streaming APIMessageRouteandTopicRoutingcorrectly throwNotSupportedExceptionfor streaming over message transports (use gRPC for remote streaming)gRPC Streaming Integration (Commit 7629b3f, 2b2fce4) ✅ Complete
Wolverine now supports a recommended architectural pattern for gRPC streaming endpoints:
IAsyncEnumerable<T>Bus.StreamAsync<T>()Example:
Benefits:
Enhanced OpenTelemetry for Streaming (Commits 296b09b, 13fa8d1) ✅ Complete
StreamingTelemetryExtensions.WithTelemetry(): Extension method for instrumentingIAsyncEnumerable<T>streams.WithTelemetry(activity, "operation-name")Telemetry Features:
Test Coverage for Streaming 📊
Added 15+ comprehensive tests across 3 test files:
CoreTests/Streaming/StreamingHandlerTests.cs(3 tests)CoreTests/Streaming/streaming_invoker_behavior_tests.cs(7 tests)Wolverine.Http.Grpc.Tests/streaming_telemetry_tests.cs(6 tests)Testing Philosophy: Wolverine tests streaming through integration tests using the public API (
IMessageBus.StreamAsync), which matches the framework's existing testing philosophy forExecutor,MessageRoute, andTopicRoutingclasses.Not Implemented Yet ⏸️
3. Proto-First gRPC Support
.protoFile Integration: Wolverine works seamlessly with.protofiles andGrpc.Tools<Protobuf Include="*.proto" />in your.csproj- no custom build steps4. Code-First gRPC Support (protobuf-net.Grpc)
[ServiceContract]and[OperationContract]attributes5. Enhanced gRPC Integration
ServiceBase<TService>abstract classes from gRPC toolingWolverine.Http.Grpc.TestsKey Files Changed
Streaming Implementation
src/Wolverine/IMessageBus.cs- AddedStreamAsync<TResponse>()public APIsrc/Wolverine/Runtime/MessageBus.cs- Implemented streaming through message bussrc/Wolverine/Runtime/Routing/IMessageInvoker.cs- Extended invoker interface for streamingsrc/Wolverine/Runtime/Handlers/Executor.cs- Added streaming execution path with telemetrysrc/Wolverine/Runtime/Handlers/NoHandlerExecutor.cs- Streaming support for no-handler casesrc/Wolverine/Runtime/Routing/MessageRoute.cs- Streaming NotSupported for remote invocationsrc/Wolverine/Runtime/Routing/TopicRouting.cs- Streaming NotSupported for topic routingsrc/Http/Wolverine.Http.Grpc/StreamingTelemetryExtensions.cs- OpenTelemetry instrumentationsrc/Testing/CoreTests/Streaming/*- Comprehensive streaming tests (15+ tests)Code Generation & gRPC Core
src/Http/Wolverine.Http.Grpc/GrpcChain.cs- Code generation for service wrapperssrc/Http/Wolverine.Http.Grpc/WolverineGrpcExtensions.cs- Service discovery and registrationsrc/Samples/ProtoFirstGrpcSample/- Proto-first examplesrc/Samples/PingPongWithGrpc/- Code-first unary examplesrc/Samples/RacerGrpcSample/- Bidirectional streaming + IMessageBus.StreamAsync integration exampleSample Projects & Documentation
All three gRPC samples demonstrate different patterns:
IMessageBus.StreamAsync<T>()integrationIAsyncEnumerable<T>and executes through middleware pipelineDocumentation Updates (Commit 2b2fce4):
docs/guide/http/grpc.mdwith comprehensive streaming handler documentationBus.StreamAsync()integrationFor Wolverine Maintainers (JasperFx Team)
This PR contains two main components:
WolverineFx.Http.Grpcpackage that does NOT change existing Wolverine behaviorIMessageBus.StreamAsync<T>()benefiting all usersKey design decisions:
GrpcEndpoint,GrpcEndpoints,GrpcService,GrpcServicessuffixes) mirrors the established Wolverine handler naming convention[WolverineGrpcService]attribute opt-in for proto-first services that must inherit proto-generated base classesWolverineGrpcEndpointBasebase class gives code-first services zero-boilerplateIMessageBusaccess via property injectionIAsyncEnumerable<T>and be consumed viaIMessageBus.StreamAsync<T>()Breaking Changes
None. This is purely additive functionality.
Testing
Wolverine.Http.Grpc.TestsCoreTests/StreamingMigration Guide
No migration needed - existing Wolverine applications are unaffected. To adopt gRPC:
For Code-First:
For Proto-First:
For Streaming:
Notes for Reviewers
GrpcChainclass generates service wrappers at build time - checkobj/folder for generated code during debuggingIAsyncEnumerable<T>- single return values are not automatically converted to streams (by design)NotSupportedException- use gRPC for remote streaming scenariosIMessageBus.StreamAsync()IMessageBus.StreamAsync) is added to core Wolverine and benefits all usersBus.StreamAsync()