feat: saga state query API and reporting endpoints (#99)#114
feat: saga state query API and reporting endpoints (#99)#114
Conversation
- Add ISagaStateQuery interface with DTOs (SagaInstanceInfo, PagedResult, etc.) - Implement query for all backends: InMemory, SQL, MongoDB - Include StateData in query results for runtime saga inspection - Add OpenSleigh.Reporting project with Minimal API endpoints - Register ISagaStateQuery in all backend DI extensions - Add pagination validation, deserialization safety, snapshot for thread safety - Add unit tests for InMemory query and reporting endpoints
A pizza order tracking sample using InMemory persistence and transport. Orders progress through 6 saga steps (Received → Preparing → Baking → Quality Check → Out for Delivery → Delivered) with ~2s delays to allow querying intermediate state via the OpenSleigh.Reporting endpoints. Demonstrates: MapOpenSleighReporting(), ISagaStateQuery, live StateData, filtering by completion status, and pagination.
Add summaries, descriptions, response types, and error codes to all saga reporting endpoints. Grouped under 'OpenSleigh' tag for Swagger UI.
Add Microsoft.AspNetCore.OpenApi with TFM-conditional versioning (8.0.24 for net8.0, 9.0.13 for net9.0, 10.0.3 for net10.0). OpenAPI spec served at /openapi/v1.json with full schema and metadata.
Use #if !NET8_0 guards for AddOpenApi/MapOpenApi calls and remove the net8.0 package reference since the API is only available in 9.0+.
The custom MSBuild property name collided with the SDK's built-in TargetFrameworkVersion property, causing VS build failures when Microsoft.AspNetCore.OpenApi package was referenced. Also moves OpenAPI into OpenSleigh.Reporting (AddOpenApi/MapOpenApi called automatically by AddOpenSleighReporting/MapOpenSleighReporting, guarded with #if NET9_0_OR_GREATER for net8.0 compat) and simplifies PizzaTracker to target net10.0 only.
- Snapshot ConcurrentDictionary in GetByCorrelationIdAsync (race condition) - Validate sagaType parameter in correlation endpoint (400 if missing) - Add XML doc security warning on MapOpenSleighReporting
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #114 +/- ##
===========================================
+ Coverage 81.63% 82.34% +0.70%
===========================================
Files 77 86 +9
Lines 2287 2571 +284
Branches 268 301 +33
===========================================
+ Hits 1867 2117 +250
- Misses 317 350 +33
- Partials 103 104 +1
... and 1 file with indirect coverage changes Continue to review full report in Codecov by Sentry.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR implements a comprehensive saga state query and reporting API for OpenSleigh, addressing issue #99. It enables runtime visibility into saga instances across all persistence backends (InMemory, SQL, MongoDB) through a unified query interface, and exposes this functionality via HTTP endpoints with OpenAPI support.
Changes:
- Added
ISagaStateQueryinterface with methods to query saga instances by ID, correlation ID, or retrieve all with filtering/pagination - Implemented query support in all persistence backends using appropriate techniques (reflection for InMemory, EF Core for SQL, MongoDB driver for Mongo)
- Created
OpenSleigh.Reportingmodule with ASP.NET Core Minimal API endpoints and OpenAPI metadata - Included PizzaTracker sample application demonstrating the query API and reporting endpoints
- Renamed MSBuild property from
TargetFrameworkVersiontoSupportedTargetFrameworksto avoid SDK collision
Reviewed changes
Copilot reviewed 58 out of 59 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
src/OpenSleigh/Queries/ISagaStateQuery.cs |
Core query interface with GetByInstanceIdAsync, GetByCorrelationIdAsync, and GetAllAsync methods |
src/OpenSleigh/Queries/SagaInstanceInfo.cs |
DTO containing saga instance metadata including live StateData |
src/OpenSleigh/Queries/SagaQueryFilter.cs |
Filter DTO for querying sagas by type and completion status with pagination |
src/OpenSleigh/Queries/PagedResult.cs |
Generic paged result DTO |
src/OpenSleigh/Queries/ProcessedMessageInfo.cs |
DTO for processed message metadata |
src/OpenSleigh.InMemory/InMemorySagaStateRepository.cs |
InMemory implementation of ISagaStateQuery using reflection to extract state data |
src/OpenSleigh.InMemory/InMemoryBusConfiguratorExtensions.cs |
DI registration mapping both ISagaStateRepository and ISagaStateQuery to singleton instance |
src/OpenSleigh.Persistence.SQL/SqlSagaStateQuery.cs |
SQL implementation using EF Core with ISerializer for state deserialization |
src/OpenSleigh.Persistence.SQLServer/SqlBusConfiguratorExtensions.cs |
DI registration for SQL Server query implementation |
src/OpenSleigh.Persistence.PostgreSQL/SqlBusConfiguratorExtensions.cs |
DI registration for PostgreSQL query implementation |
src/OpenSleigh.Persistence.Mongo/MongoSagaStateQuery.cs |
MongoDB implementation using driver with ISerializer for state deserialization |
src/OpenSleigh.Persistence.Mongo/MongoBusConfiguratorExtensions.cs |
DI registration for MongoDB query implementation |
src/OpenSleigh.Reporting/Endpoints/SagaEndpoints.cs |
Minimal API endpoint handlers with validation for pagination and required parameters |
src/OpenSleigh.Reporting/EndpointRouteBuilderExtensions.cs |
Extension method to map reporting endpoints with OpenAPI metadata and security documentation |
src/OpenSleigh.Reporting/ServiceCollectionExtensions.cs |
DI extension to register OpenAPI for .NET 9+ |
src/OpenSleigh.Reporting/OpenSleigh.Reporting.csproj |
New reporting module project with framework-specific OpenAPI package references |
tests/OpenSleigh.Tests/Queries/InMemorySagaStateQueryTests.cs |
Comprehensive unit tests (13 tests) for InMemory query implementation |
tests/OpenSleigh.Reporting.Tests/SagaEndpointsTests.cs |
Unit tests (13 tests) for reporting endpoints including validation scenarios |
samples/OpenSleigh.Samples.PizzaTracker/* |
Complete sample application demonstrating query API and reporting endpoints |
Versions.props |
Renamed TargetFrameworkVersion to SupportedTargetFrameworks |
.gitignore |
Added .claude/settings.local.json |
src/OpenSleigh.sln |
Added new projects and build configurations |
All .csproj files |
Updated to use $(SupportedTargetFrameworks) |
- 16 unit tests for SqlSagaStateQuery using EF Core InMemory provider (queries, filtering, pagination, state deserialization, lock detection) - 3 tests for GetByCorrelationId sagaType validation (null/empty/whitespace) - Total: 293 tests passing
Summary
Implements runtime saga state visibility as requested in #99. Adds a query interface, persistence implementations for all backends, HTTP reporting endpoints with OpenAPI support, and a sample application.
Changes
Core Query API (
OpenSleigh)ISagaStateQueryinterface withGetByInstanceIdAsync,GetByCorrelationIdAsync, andGetAllAsyncmethodsSagaInstanceInfo(withStateDatafor live saga state),ProcessedMessageInfo,SagaQueryFilter,PagedResult<T>Persistence Implementations
InMemorySagaStateRepositorynow implementsISagaStateQuery, extracting live state via reflectionSqlSagaStateQueryusing EF Core withISerializerfor state deserializationMongoSagaStateQueryusing MongoDB driver withISerializerfor state deserializationISagaStateQueryin their DI extensionsReporting Module (
OpenSleigh.Reporting)GET /sagas,GET /sagas/{id},GET /sagas/correlation/{id},GET /sagas/typesAddOpenApi/MapOpenApi) built-in for .NET 9+sagaTyperequired)Sample Application
samples/OpenSleigh.Samples.PizzaTracker): Pizza order tracking with 6-step saga flow, demonstrating real-time state queries via reporting endpointsInfrastructure
TargetFrameworkVersiontoSupportedTargetFrameworksinVersions.propsto fix MSBuild property collision with SDK built-in.claude/settings.local.jsonto.gitignoreSafety and Thread Safety
.ToList()) before enumeration in all InMemory query methodsLockIdandLockTimeconsistentlyTests
Closes #99