Releases: JasperFx/wolverine
V5.36.0
What's Changed
- Add IAgent.Description for monitoring-tool tooltips by @jeremydmiller in #2645
- feat: AES-256-GCM message encryption with send/receive enforcement (#2643) by @BlackChepo in #2644
- fix(rdbms-inbox): discard duplicate Kafka messages instead of freezing the partition (#2639) by @BlackChepo in #2648
- Prevent leadership re-election every 5 minutes by @Bishbulb in #2625
- Enrich DurabilityAgent.CheckHealthAsync with persistence-layer signals (#2646) by @jeremydmiller in #2649
- Native API versioning for Wolverine.Http (closes #2627) by @outofrange-consulting in #2633
- Enrich StickyPostgresqlQueueListenerAgent.CheckHealthAsync with listener-state signals (#2647) by @jeremydmiller in #2650
- fix(rdbms-inbox): align RavenDb and CosmosDb batch inbox with #2648 duplicate-envelope contract by @BlackChepo in #2651
- Surface 'Custom' interop mode + DefaultSerializerDescription on EndpointDescriptor (#2641) by @jeremydmiller in #2652
- 5.36: routing-precedence regression fix + metrics test repair + 5.36.0 cut by @jeremydmiller in #2655
- feat(durability): AlwaysMakeScheduledMessagesDurable policy by @jeremydmiller in #2657
Full Changelog: V5.35.2...V5.36.0
V5.35.2
What's Changed
A small bug-fix and dependency-refresh release.
Persistence fixes
- Oracle: timestamp default expressions now survive non-UTC DB sessions (#2634) —
OracleMessageStore.Initializeand the surrounding schema declared timestamp columns (health_check,started,posted, etc.) with a DEFAULT ofSYS_EXTRACT_UTC(SYSTIMESTAMP). That returns a TIMESTAMP without a time zone, and when implicitly cast into theTIMESTAMP WITH TIME ZONEcolumn Oracle stamps it with the session time zone — so for any session in UTC+N the just-persisted value's UTC equivalent was N hours in the past. That tripped theNodeAgentController.DoHealthChecksAsyncstaleness filter and surfaced as aNullReferenceExceptionduring the first leadership-election heartbeat (self!.AssignAgents([LeaderUri])on anullself). All 18 occurrences swapped toSYSTIMESTAMP AT TIME ZONE 'UTC', with quote-doubling for the DDL contexts that go through Weasel'sEXECUTE IMMEDIATE '...'wrapper.
Reliability hardening
- Lock
dbcontrol://andoraclecontrol://endpoints toBufferedInMemory(#2637) — the database-backed control transport carries inter-node leader-election and agent-reassignment commands. Marking either endpoint Durable would route every control envelope through the same store-backed inbox/outbox the durability agent itself owns (deadlock); marking it Inline contradicts the batched-poll semantics. BothDatabaseControlEndpointandOracleControlEndpointnow overridesupportsModeso any policy that tries to flip them offBufferedInMemoryeither silently skips (UseDurableInboxOnAllListeners,UseDurableOutboxOnAllSendingEndpoints, etc., already checkSupportsMode) or fails fast with a clearInvalidOperationException.
Source-gen / startup
- Aggregate
IWolverineTypeLoaderacross all known assemblies (#2632) by @devployment — since 5.34.0, hosts on the source-generated codegen path silently dropped handlers that lived in referenced assemblies becausetryDiscoverTypeLoaderFromAttributeonly inspectedOptions.ApplicationAssembly. First invocation of one of those handlers threwIndeterminateRoutesException. The runtime now walksApplicationAssemblyand every assembly inDiscovery.Assemblies, collects every[WolverineTypeManifest]loader it finds, and exposes their union via the new internalCompositeWolverineTypeLoader. Existing single-loader semantics are preserved when only one manifest is found.
Other
- Saga timeout flag + scheduled-dispatch Activity tag (#2631) by @jeremydmiller — surfaces saga timeout and scheduled-dispatch metadata so the upcoming CritterWatch saga visualization can render in-flight saga state.
Dependencies
- Bump JasperFx 1.28.0 → 1.28.2 and JasperFx.Events 1.29.0 → 1.31.1 (#2638).
Full Changelog: V5.35.1...V5.35.2
V5.35.1
What's Changed
A bug-fix and small-feature release covering Oracle-in-Balanced-mode startup, a duplicate-poller defect on RavenDb, an AWS SQS sharded-slot naming fix, and a new SagaDescriptor surface for CritterWatch.
Persistence fixes
-
Oracle in
DurabilityMode.Balancednow boots (#2622) —OracleMessageStore.Initializewas a no-op, so hosts using Oracle persistence in Balanced mode failed to start withArgumentOutOfRangeException("ControlEndpoint cannot be null for this usage"). The fix mirrorsMessageDatabase.Initializefor Oracle and stands up a parallelOracleControlTransport/OracleControlEndpoint/OracleControlSender/OracleControlListenerset under the neworaclecontrol://protocol — necessary because the sharedDatabaseControlSender/DatabaseControlListenerassume@-prefixed placeholders and Guid values that map directly onto aDbParameter, neither of which Oracle accepts (:-prefixed placeholders,RAW(16)id columns requiringbyte[]). Also fixes a latentOracleMessageStore.EnqueueAsyncno-op that leftLogRecordsAsyncsilently dropping node records, and makesFetchRecentRecordsAsyncDBNull-safe on the description column. Adds a newOracleTests.LeaderElectionproject so the leadership-compliance suite runs against Oracle (marked[Trait("Category","Flaky")]because the suite needs careful TM/DML lock sequencing between back-to-back runs). -
RavenDb: only one durability agent polls after host start (#2623, #2629) by @Bishbulb (root-cause investigation and original fix) and @jeremydmiller —
RavenDbMessageStore.StartScheduledJobseagerly built and started aRavenDbDurabilityAgentat boot in addition to the agent thatNodeAgentControlleralready builds and starts viaIAgentFamily/MessageStoreCollection. TwoRavenDbDurabilityAgentinstances then polled the same database concurrently, both believed they held the scheduled-job lock, raced to mark the same envelopesIncoming, and surfacedConcurrencyExceptionplus double-fired timeouts. Drops the eagerStartTimers()call; the cluster-managed agent is now the single owner of polling. The agent returned fromStartScheduledJobsis held byWolverineRuntime.DurableScheduledJobspurely for its disposal-timeStopAsync. Comes with a reflection-free regression test (addedRavenDbDurabilityAgent.IsPollingandCompositeAgent.InnerAgentsfor the test to enumerate without poking at private fields). A companion regression-guard test for CosmosDb is included; investigation showed the equivalent CosmosDb path does NOT have the bug today (CosmosDbMessageStore.BuildAgentFamilyreturns null andUriuses thecosmosdb://scheme rather thanwolverinedb://, soMessageStoreCollectionnever registers a competing agent).
Other improvements
-
AWS SQS: correct naming for sharded slot endpoints in #1f294ce5 — fixes a regression where sharded slot endpoint URIs were assembled with the wrong segment ordering, causing the consumer side to listen at the wrong queue.
-
SagaDescriptorexported viaServiceCapabilitiesin #f0998c7b — adds a saga-shape descriptor (saga type, id type, current state) to the capabilities exporter so CritterWatch can surface saga inventory and current state in its dashboard.
Full Changelog: V5.34.0...V5.35.1
V5.34.0
What's Changed
This release introduces three new features (Claim Check pattern, declarative Polecat data requirements, and a new opt-in WolverineFx.RuntimeCompilation package as the first step toward AOT compatibility), a fix for a long-standing service-location footgun, several real RavenDB and EF Core durability fixes, plus the cold-start prep work done as part of issue #1577.
Highlights
- Add Claim Check / DataBus pattern with
[Blob]attribute (#2412) by @jeremydmiller in #2617 — off-load large message-property payloads to external storage on send and re-hydrate them on receive, so the on-the-wire envelope stays small. Core abstractions (IClaimCheckStore,ClaimCheckToken,[Blob],FileSystemClaimCheckStore,opts.UseClaimCheck(...)) live inWolverine.Persistence. Two new backend NuGet packages ship alongside:WolverineFx.ClaimCheck.AzureBlobStorageandWolverineFx.ClaimCheck.AmazonS3. New documentation page under/guide/durability/claim-checks. - Declarative data-requirement attributes for Polecat (#2552) by @jeremydmiller in #2615 —
[DocumentExists<T>],[DocumentDoesNotExist<T>], andPolecatOps.Document<T>().MustExist(...)/.MustNotExist(...)mirror the Marten ergonomics, with the same batch-query optimization that folds multiple existence checks into a single PolecatIBatchedQueryround-trip. - Service-located
IMessageBus/IMessageContextnow see the active context (#2583) by @jeremydmiller in #2616 — when user code service-locatesIMessageBus(e.g., constructor injection on a service the handler resolves at runtime), it now receives the sameMessageContextthe handler itself uses, preserving outbox semantics. Implemented as a per-chain opt-in (gated onChain.UsesServiceLocation) so chains that don't service-locate pay zeroAsyncLocaloverhead per message. - Cold-start optimizations and
WolverineFx.RuntimeCompilationopt-in package (#1577) by @jeremydmiller in #2613 and #cc00ca0a — first pass at the cold-start / AOT roadmap. Wires theWolverine.SourceGenerationanalyzer into theWolverineFxNuGet output (so source-generatedIWolverineTypeLoaderdiscovery flows transitively to consumers), pre-populates theWolverineMessageNamingcache during startup to eliminate first-message reflection cost, applies[DynamicallyAccessedMembers]annotations on theActivator.CreateInstancecall sites for trimmer-friendliness, and addsConfigureAwait(false)across 117 awaits on the per-message hot path. The newWolverineFx.RuntimeCompilationpackage becomes the future-facing opt-in API for runtime Roslyn compilation; default behavior is preserved.
RavenDB durability fixes
- Fix bulk RavenDB inbox store leaking duplicates as inbox-unavailable (#2606) by @Bishbulb in #2606
- Take over expired RavenDB scheduled-job and leadership locks (#2608) by @Bishbulb in #2608
- Disable optimistic concurrency on RavenDB cluster-wide node sessions; load-then-modify on agent-assignment writes (#2610) by @Bishbulb in #2610
EF Core / ancillary stores
- Fix
DurableLocalQueueto route incoming envelopes to ancillary stores (#2611) by @jeremydmiller — handler chains targeting an ancillary message store now have their incoming envelopes persisted in that store rather than the main store, fixing a class of "envelope stuck as Incoming forever" bugs. - Fix
WolverineEnabledannotation collision in ancillary-store EF Core scenarios as part of #2618 —MapWolverineEnvelopeStorageis now idempotent when called against the same model graph more than once.
Other improvements
- Fix
MessageBusclobbering per-messageEnvelope.Sourcein #26e38002 —MessageBus.Sendwas overwriting the per-messageSourcewith the host'sServiceName, masking the originating service in causation tracking. - Surface upcoming
ServiceLocationPolicy.NotAllowedv6 default (#2584) by @jeremydmiller in #2609 — chains that resolve dependencies via service location now log a warning at codegen time, with a clear migration path to the new opt-inWolverine.RuntimeCompilationstory for v6.
CI stabilization
- Several flaky test classes fixed or marked in #2612 and #2618 — timeout bumps,
IDisposable→IAsyncLifetimeconversions, lifecycle cleanup; chronically broken-on-CI classes (SqliteTests.Transport.multi_tenancy_with_multiple_files,CosmosDbTests.LeaderElection.leader_election,Wolverine.RabbitMQ.Tests.send_by_topics,Wolverine.RabbitMQ.Tests.sending_raw_messages) tagged[Trait("Category", "Flaky")]with header comments documenting the symptom and the real follow-up fix. - JasperFx 1.28 / RuntimeCompiler 4.5 ambiguity fallout fixed in #2618 — files importing both
JasperFx.CodeGenerationandJasperFx.RuntimeCompilernow compile cleanly after theInitializeSynchronouslyextension method was moved intoJasperFx.CodeGenerationupstream.
Issue-tracker housekeeping
#2507(Quartz.Net / TickerQ first-class integration) added to the 6.0 milestone with a phased plan documented on the issue.#1577(cold-start optimization roadmap) updated with a six-phase plan and current-state checklist; phases 1–4 are non-breaking on v5.x and largely landed in this release.
Full Changelog: V5.33.0...V5.34.0
V5.33.0
What's Changed
This release includes a major reliability fix for distributed leader election, a port of the Polecat 2.x event store integration, and several other quality-of-life improvements.
Highlights
- Fix #2602: Leader split-brain via stale advisory lock by @jeremydmiller in #2607 — three-layer defensive fix that detects when a Postgres/SQL Server/MySQL/Oracle/SQLite advisory lock has been silently released server-side, steps down the local leader, releases its agents, and triggers a fresh leader election. Adds a new
LeadershipLostnode record type and anIWolverineObserver.LostLeadership()hook for monitoring. - Polecat 2.x event store integration by @jeremydmiller in #2598 — ports the aggregate handler workflow from Marten so SQL Server-backed projects can use Polecat as a native event store with Wolverine. Requires SQL Server 2025 for the native
JSONtype. - Fix #2571: Preserve context fields on scheduled-send wrap/unwrap by @jeremydmiller in #2605 — saga IDs, tenant IDs, and other correlation fields now survive the scheduled-send envelope round-trip.
- gRPC enhancements by @jeremydmiller in #2565 — middleware weaving, validate convention, user exception mapping, bidirectional streaming, code-first codegen, plus new samples.
- Allow RabbitMQ exchanges to be declared passive by @jeremydmiller in #2574
Other Improvements
- Move non-sticky-handlers guard inside the compile lock by @jeremydmiller in #2556
- Add
launchSettings.jsonto sample projects by @jeremydmiller in #2600
Full Changelog: V5.32.1...V5.33.0
What's Changed
- Update vulnerable OpenTelemetry dependencies by @dmytro-pryvedeniuk in #2590
- Fix tenant partitioning precedence with inferred grouping by @erdtsieck in #2581
- Use quoted schema names in SQL statements for RDBMS persistence by @esskar in #2577
- Skip logging when the count is zero by @Bishbulb in #2560
- Accept *Async suffix on saga method names (#2578) by @jeremydmiller in #2593
- Fix ancillary store scheduled messages stuck Incoming forever (#2576) by @jeremydmiller in #2591
- Add Wolverine.SourceGeneration to slnx (supersedes #2575) by @jeremydmiller in #2592
- Honor [Consumes] / IAcceptsMetadata on form endpoints by @rmasciarella in #2589
- Materialize EF domain-event scraper before publishing (#2585) by @jeremydmiller in #2594
- Process Manager via Handlers sample by @erikshafer in #2579
- Fix missing ParameterDescriptor for form parameters in API descriptions by @rmasciarella in #2587
- Allow configuration of the MessageBatchTimeout by @lyall-sc in #2582
- Fix #2588: durable outbox policy ignored for conventionally-routed senders by @jeremydmiller in #2596
- Fix #2595: explicit DeliveryOptions.SagaId on saga Start cascades should win by @jeremydmiller in #2597
- Allow RabbitMQ exchanges to be declared passive by @saithis in #2574
- Fix NoHandlerForEndpointException during concurrent saga chain compile by @Bishbulb in #2556
- gRPC: Middleware Weaving, Validate Convention, User Exception Mapping, Bidi Streaming, Code-First Codegen, New Samples by @erikshafer in #2565
- Add launchSettings.json files to the sample projects by @dmytro-pryvedeniuk in #2600
- Fix #2571: preserve context fields on scheduled-send wrap unwrap by @jeremydmiller in #2605
- Add Endpoint.BrokerRole for CritterWatch endpoint display (#2601) by @jeremydmiller in #2603
- Process Manager via Handlers Cleanup by @erikshafer in #2604
- Fix #2602: leader split-brain via stale advisory-lock state by @jeremydmiller in #2607
- Polecat parity port from Wolverine.Marten + Polecat 2.1.0 bump by @jeremydmiller in #2598
New Contributors
- @esskar made their first contribution in #2577
- @rmasciarella made their first contribution in #2589
- @saithis made their first contribution in #2574
Full Changelog: V5.32.1...V5.33.0
V5.32.1
What's Changed
- Fix RavenDb scheduled messages not being delivered when using a durable transport by @Bishbulb in #2554
- Fix NRE in RavenDb durability recovery by @Bishbulb in #2555
- Add gRPC message transport to Wolverine.Grpc by @jeremydmiller in #2559
- docs: cross-link shared-libs.jasperfx.net and weasel.jasperfx.net by @jeremydmiller in #2563
- Resolve merge conflict for RavenDb CI PR by @erdtsieck in #2564
- Add CI target and workflow for RavenDb (GH-2558) by @jeremydmiller in #2561
- Exempt Wolverine's Envelope from blanket multi-tenant doc policies (supersedes #2566 / marten#4268) by @jeremydmiller in #2570
- Fix Kafka native DLQ sending to source topic instead of DLQ topic by @lyall-sc in #2569
- Update vulnerable dependencies by @dmytro-pryvedeniuk in #2568
- Fix EnvelopeMapper swapped filter predicates breaking single-direction property overrides (#2551) by @jeremydmiller in #2573
New Contributors
Full Changelog: V5.32.0...V5.32.1
V5.32.0
What's Changed
- Add query-plan (Specification pattern) support for EF Core by @jeremydmiller in #2526
- Auto-execute Marten query specifications from Load methods + [FromQuerySpecification] by @jeremydmiller in #2531
- Add transport endpoint URI helpers for all supported transports (#2502) by @BlackChepo in #2533
- EF Core parallel of Marten fetch-specifications + cross-provider [FromQuerySpecification] by @jeremydmiller in #2532
- Lowercase all mdsnippets snippet names by @jeremydmiller in #2534
- Fix silent message loss from concurrent PublishAsync on MessageContext by @jeremydmiller in #2536
- Add StreamOne/StreamMany/StreamAggregate helpers for Wolverine.Http.Marten by @jeremydmiller in #2528
- gRPC Support for Wolverine HTTP Endpoints + IMessageBus.StreamAsync by @erikshafer in #2525
- Fix DLQ replay loop for buffered local queues (GH-1942) by @jeremydmiller in #2538
- Make Kafka AutoProvision actually create missing topics (GH-2537) by @jeremydmiller in #2540
- Adds MapIncomingProperty method to EnvelopeMapper by @Ferchke7 in #2541
- gRPC #2525 follow-up: Correctness Gaps by @erikshafer in #2542
- EF Core dev-time improvements (GH-2539) by @jeremydmiller in #2543
- docs: LoadAsync / strong-typed id codegen sample (GH-2508) by @jeremydmiller in #2544
- OptionsDescription audit: clean transport rendering + secret-safe connection info by @jeremydmiller in #2549
- Per-message metadata override for projection side-effect publishing (GH-2545) by @jeremydmiller in #2550
Full Changelog: V5.31.1...V5.32.0
V5.31.1
What's Changed
- Replace Encoding.Default with Encoding.UTF8 for clarity by @BlackChepo in #2516
- Fix [SagaIdentityFrom] ignored when NotFound declared before Handle by @jeremydmiller in #2522
- Acquire advisory lock around message database migrations by @jeremydmiller in #2523
- Filter framework-internal message types from observability surfaces by @jeremydmiller in #2524
Full Changelog: V5.31.0...V5.31.1
V5.31.0
What's Changed
- Fix missing bracket in LogStartingActivity log message by @jeremydmiller in #2498
- Fix broken link to RabbitMQ .NET API guide by @Shield1739 in #2499
- Expose FluentValidation configuration through UseFluentValidation overload by @outofrange-consulting in #2497
- Add jitter support to retry cooldown policies (#2501) by @BlackChepo in #2504
- Add fluent CircuitBreaker configuration to Kafka listeners by @Ferchke7 in #2506
- Add soft-deleted saga experiment and documentation by @jeremydmiller in #2503
- Fix silent message loss when envelope mapper throws (RabbitMQ + MQTT) by @BlackChepo in #2511
- Add TenantId overloads to all MartenOps and PolecatOps types by @jeremydmiller in #2512
- Fix CI failures from PR #2511 by @jeremydmiller in #2515
New Contributors
Full Changelog: V5.30.0...V5.31.0
V5.30.0
This release is mostly about CritterWatch or the new AI skills usage with a few housekeeping issues
What's Changed
- Solution housekeeping: migrate to slnx, reorganize projects by @jeremydmiller in #2461
- Expose WolverineOptions.MetadataRules publicly by @lyall-sc in #2464
- Fix Turkish culture (dotless-i) corruption of SQL identifiers by @jeremydmiller in #2480
- Fix EfCoreEnvelopeTransaction batch outgoing envelopes using wrong storage command by @jeremydmiller in #2479
- Fix strong-typed saga ID causing CS0246 code generation error by @jeremydmiller in #2481
- Parallelize tenant database initialization in EnsureAllTenantDatabasesCreatedAsync by @jeremydmiller in #2482
- Use AddRange in EfCoreEnvelopeTransaction for batch outgoing inserts by @jeremydmiller in #2483
- Fix O(n) ChangeTracker full scan in DomainEventScraper (#2476) by @jeremydmiller in #2484
- Add wolverine-diagnostics codegen-preview CLI command by @jeremydmiller in #2486
- Auto-detect metadata-only CLI mode to suppress DB/transport init by @jeremydmiller in #2485
- Upgrade JasperFx and Weasel NuGet packages by @jeremydmiller in #2490
- Add IHandlerConfiguration interface for compile-time safe Configure(HandlerChain) (#2466) by @jeremydmiller in #2491
- Tag OTEL spans with saga ID/type and aggregate stream ID/type by @jeremydmiller in #2489
- Add describe-routing sub-command to wolverine-diagnostics (#2468) by @jeremydmiller in #2487
- Adopt Weasel IDatabaseCleaner and BatchedQuery EF Core APIs (#2473, #2478) by @jeremydmiller in #2492
- Release 5.30.0 by @jeremydmiller in #2493
- Remove OTEL Activity from circuit breaker to fix trace ID leak by @jeremydmiller in #2495
Full Changelog: V5.29.0...V5.30.0