Skip to content

Bump JasperFx pins to alpha.12 / Events alpha.7 + AOT chunk M - #2806

Merged
jeremydmiller merged 14 commits into
mainfrom
chore/bump-jasperfx-pins-alpha12
May 15, 2026
Merged

jeremydmiller merged 14 commits into
mainfrom
chore/bump-jasperfx-pins-alpha12

Conversation

@jeremydmiller

@jeremydmiller jeremydmiller commented May 14, 2026 •

Copy link
Copy Markdown
Member

Summary

Bumps Wolverine's central package pins to:

…and lands AOT chunk M alongside (per #2746): the per-file annotation propagation needed because alpha.11/12 added stricter [RequiresUnreferencedCode] / [RequiresDynamicCode] annotations on JasperFx APIs that Wolverine.csproj wraps.

JasperFx.RuntimeCompiler and JasperFx.SourceGeneration left at 2.0.0-alpha.2 (no newer alphas published).

AOT chunk M scope

JasperFx surfaces gaining new annotations between alpha.10 and alpha.12:

  • MethodCall(Type, String) — codegen reflective constructor
  • OptionsDescription(Object) / AddChildSet(...) — diagnostic property reflection
  • DatabaseDescriptor(Object) — same shape
  • IServiceContainer.QuickBuild(Type) — [FromKeyedServices] resolution closes IFinder<T>
  • TypeQuery.Find(...) / AssemblyFinder.FindAssemblies(...) — handler / module discovery
  • LambdaBuilder.GetProperty<,> — FastExpressionCompiler property accessor
  • TypeExtensions.Closes / FindInterfaceThatCloses — generic-interface graph inspection
  • RunJasperFxCommands / AddJasperFx — command-line bootstrap
  • SystemPartBase.WriteToConsole (base method) — required matching annotation on override

27 files touched in src/Wolverine/. Pattern matches chunks A–L:

  • Class-level [UnconditionalSuppressMessage] on codegen / diagnostic-only sites
  • DAM annotations on parameters / fields flowing into the newly-annotated JasperFx APIs
  • Full [RequiresUnreferencedCode] / [RequiresDynamicCode] propagation on user-facing public surfaces (RunWolverineAsync, AddMiddleware(Type, String), AddPostprocessor(Type, String)) so downstream user code gets informative warnings rather than raw IL2026/IL3050 into JasperFx internals

Verification

Files touched (chunk M)

  • Configuration/Capabilities/{BrokerDescription,EndpointDescriptor,MessageHandlerDescriptor}.cs
  • Configuration/HandlerDiscovery.cs
  • Configuration/IChain.cs
  • ExtensionLoader.cs
  • HostBuilderExtensions.cs
  • Persistence/ApplyAncillaryStoreFrame.cs
  • Persistence/Durability/{MultiTenantedMessageStore,NullMessageStore}.cs
  • Persistence/FlushOutgoingMessages.cs
  • Persistence/Sagas/{CreateMissingSagaFrame,CreateNewSagaFrame,LightweightSagaPersistenceFrameProvider,SagaChain,SagaStorageVariableSource}.cs
  • Persistence/Storage.cs
  • Runtime/Handlers/{HandlerCall,HandlerChain,HandlerGraph}.cs
  • Runtime/Partitioning/MessagePartitioningRules.cs
  • Runtime/Serialization/Forwarders.cs
  • Shims/MassTransit/ConsumeContextVariableSource.cs
  • Util/WolverineMessageNaming.cs
  • WolverineOptions.{Description,Forwarders}.cs
  • WolverineSystemPart.cs

Test plan

  • Pre-bump baseline (alpha.10): builds clean
  • Post-bump + chunk M: builds clean
  • AotSmoke regression-guard: builds clean
  • CI runs full Wolverine.Tests against the new pins

jeremydmiller and others added 3 commits May 14, 2026 09:31
Picks up the AOT-pillar annotation sweep + the TPL Dataflow removal +
the [Obsolete] cleanup sweep that landed in JasperFx between
alpha.10 and alpha.12.

JasperFx.RuntimeCompiler and JasperFx.SourceGeneration pins are left
at 2.0.0-alpha.2 since no newer alpha is published.

KNOWN GATE: this bump currently produces 106 IL2026/IL2067/IL3050/etc.
trim errors against Wolverine.csproj — JasperFx alpha.12 added stricter
AOT annotations on the codegen / descriptor / reflection helpers, and
Wolverine's core handler-chain types (HandlerChain, HandlerCall,
IChain, HandlerDiscovery, WolverineOptions.Description,
HostBuilderExtensions, …) need a matching AOT-chunk annotation pass
before this can merge. The rolling AOT chunks AJ/AK/AL covered
Wolverine.Newtonsoft / DataAnnotationsValidation / FluentValidation;
the core Wolverine.csproj chunk is the missing piece. Filing as draft
so the chunk can stack on top.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Picks up the additional [RequiresUnreferencedCode]/[RequiresDynamicCode]
annotations that JasperFx alpha.11/12 added on top of the alpha-10 AOT
substrate — same chunk-A-through-L pattern, just incremental to keep
Wolverine.csproj clean under the pin bump in this PR.

JasperFx surfaces gaining annotations (top offenders):

- JasperFx.CodeGeneration.Frames.MethodCall.MethodCall(Type, String)
- JasperFx.Descriptors.OptionsDescription.OptionsDescription(Object)
- JasperFx.Descriptors.OptionsDescription.AddChildSet(...)
- JasperFx.Descriptors.DatabaseDescriptor.DatabaseDescriptor(Object)
- JasperFx.IServiceContainer.QuickBuild(Type)
- JasperFx.Core.TypeScanning.TypeQuery.Find(...)
- JasperFx.Core.TypeScanning.AssemblyFinder.FindAssemblies(...)
- JasperFx.Core.Reflection.{LambdaBuilder.GetProperty, TypeExtensions.Closes/FindInterfaceThatCloses}
- JasperFx.CommandLineHostingExtensions.RunJasperFxCommands
- JasperFx.JasperFxServiceCollectionExtensions.AddJasperFx
- JasperFx.CommandLine.Descriptions.SystemPartBase.WriteToConsole

27 files touched, ~26 of them taking either a class-level
[UnconditionalSuppressMessage] (codegen / diagnostic-only sites) or a
DAM annotation on parameters / fields that flow into the newly-
annotated JasperFx APIs. Public-facing surfaces that wrap JasperFx
commands (RunWolverineAsync, AddMiddleware/AddPostprocessor(Type, String))
get full [RequiresUnreferencedCode]/[RequiresDynamicCode] propagation
so downstream user code sees informative warnings rather than raw
IL2026/IL3050 into JasperFx internals — matches the docs/guide/aot.md
pattern established by chunks A–L.

Verification:
- Wolverine.csproj builds clean: 0 warnings / 0 errors on net9.0 + net10.0
- Wolverine.AotSmoke regression-guard builds clean (the canary for the
  AOT-clean public-API subset)

Combined with the JFx 2.0.0-alpha.12 / Events 2.0.0-alpha.6 pin bump
in the same PR, the Wolverine 6.0 release wave's AOT-clean declaration
stays honest against the latest published JasperFx alphas.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
alpha.7 is the first published JFx.Events containing the StreamCompactingRequest<T>
and IEventBoundary<T> lifts (JasperFx #269 + #270 / PRs #274 + #275).
Wolverine doesn't directly consume those lifted contracts (they're
Marten/Polecat surfaces), but pinning the same alpha as Marten and
Polecat keeps the wave coherent.

Build remains clean (0 warnings / 0 errors) after chunk M.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jeremydmiller jeremydmiller changed the title Bump JasperFx pins to alpha.12 / Events alpha.6 (draft — gated on Wolverine.csproj AOT chunk) Bump JasperFx pins to alpha.12 / Events alpha.7 + AOT chunk M May 14, 2026
jeremydmiller and others added 4 commits May 14, 2026 13:52
…ities

Replaces the alpha.12/alpha.7 pin from earlier in this PR with the
matched alpha.13/alpha.8 pair (the post-TPL-Dataflow-removal +
post-dedupe-pillar-lifts publish). Pairs with JasperFx/jasperfx@91de11e.

CHUNK M EXTENSIONS (CI surfaced these after the initial chunk M pass
in commit aefbf35 covered only src/Wolverine/):

- src/Persistence/Wolverine.RDBMS/ConnectionSource.cs (ConnectionFrame<T>)
- src/Persistence/Wolverine.RavenDb/Internals/RavenDbMessageStore.cs
  (Describe — DatabaseDescriptor reflection)
- src/Http/Wolverine.Http/CodeGen/{AsParameters,Form}BindingFrame.cs
  (IsClassOrNullableClassNotCollection IL2067)
- src/Http/Wolverine.Http/HttpChain.cs (_handlerType DAM)
- src/Http/Wolverine.Http/HttpChain.EndpointBuilder.cs (buildHandler
  QuickBuild IL2026 / IL2077 / IL3050)
- src/Http/Wolverine.Http/HttpChain.Codegen.cs (AttachTypesSynchronously
  _handlerType IL2074)
- src/Extensions/Wolverine.FluentValidation/WolverineFluentValidationExtensions.cs
  (Scan IL3050 + HasConstructorsWithArguments IL2067)

WOLVERINE.MARTEN AMBIGUITIES (caused by JFx.Events alpha.8 lifts of
types previously only in Marten — IEventStream<T>, IEventBoundary<T>,
IEventStoreOperations now exist in both namespaces simultaneously until
Marten 9 picks up JasperFx/marten#4403):

- Distribution/WolverineProjectionCoordinator.cs — qualify
  IProjectionCoordinator<T> / IProjectionCoordinator with
  `global::Marten.Events.Daemon.Coordination`.
- Codegen/EventStoreFrame.cs + Codegen/SessionVariableSource.cs —
  drop `using JasperFx.Events;` to disambiguate IEventStoreOperations
  in favor of the Marten side (the Marten interface inherits the
  lifted contract).
- AggregateHandlerAttribute.cs + AggregateHandling.cs — qualify
  IEventStream<> references with `global::Marten.Events` (22 sites
  across the two files).
- BoundaryModelAttribute.cs + Codegen/LoadBoundaryFrame.cs — qualify
  IEventBoundary<> references with `global::Marten.Events.Dcb` (4
  + 1 sites).

WOLVERINE.MARTEN AOT GAPS (incremental — 3 sites surfaced by alpha.13's
tighter annotations on top of the lift work above):

- AggregateHandlerAttribute.cs:ActionSource.Frames — IL2062 / IL3050
  on MakeGenericType(IEventStream<>) at codegen time.
- AggregateHandling.cs:RelayAggregateToHandlerMethod — IL2065 / IL3050
  on MakeGenericType(IEventStream<>).GetProperty(Aggregate).
- BoundaryModelAttribute.cs:Modify — IL2065 / IL3050 on
  MakeGenericType(IEventBoundary<>).GetProperty(Aggregate).

All three are leaf-level UnconditionalSuppressMessage on codegen-time
sites with the standard "AOT consumers pre-generate via
TypeLoadMode.Static" justification.

Verification:

    dotnet build wolverine_slim.slnx -c Release
    Build succeeded.
        0 Warning(s)
        0 Error(s)

Once Marten 9 picks up JasperFx/marten#4403 and drops the duplicated
types from Marten.Events.Dcb / Marten.Events.IEventStoreOperations /
Marten.Events.IEventStream<T>, the `global::Marten...` qualifications
here can be reverted to bare references.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CI surfaced the third wave of chunk M overflow after the EFCore project
build was reached. Same pattern as the Wolverine.csproj +
Wolverine.RDBMS / RavenDb / Http / FluentValidation / Marten sweeps —
alpha.13's tighter annotations on JasperFx APIs need Wolverine-side
suppressions on the call sites that wrap them.

Annotated:

- Internals/Migrations/EntityFrameworkCoreSystemPart.cs:WriteToConsole
  — [RequiresUnreferencedCode] propagation to match ISystemPart base
  (IL2046 + the IL2026 from OptionsDescription.For inside).
- Codegen/EFCorePersistenceFrameProvider.cs:TryBuildFetchSpecificationFrame
  — IL2072 suppression on Variable.VariableType flowing into
  FindInterfaceThatCloses for IQueryPlan<,> / IBatchQueryPlan<,>.
- Codegen/EFCoreQuerySpecificationPolicy.cs:IsEfCoreSpecification —
  IL2067 suppression on the type parameter (same FindInterfaceThatCloses
  pattern).
- Codegen/FetchSpecificationFrame.cs:.ctor — IL2072 suppression on the
  spec-variable VariableType.
- Internals/DbContextUsageSource.cs:HasAnyQueryFilter — IL2075
  suppression on EF Core's IEntityType.GetType().GetMethod (EF8/9/10
  compatibility shim; EF Core preserves its own concrete-type members).
- Internals/DbContextUsageSource.cs:DatabaseDescriptorFactory.FromDbContext
  — IL2026 suppression on DatabaseDescriptor(dbContext) reflective
  property read (diagnostic surface).
- DbContextExtensions.cs:EnsureDatabaseExistsAsync — IL2072 suppression
  on Activator.CreateInstance(conn.GetType(), ...) (provider-specific
  DbConnection subclass is preserved by the EF provider package).
- Internals/PendingMigrationsProbe.cs:RunAsync — [RequiresDynamicCode]
  propagation on EF Core's GetPendingMigrationsAsync (migrations are
  not supported with NativeAOT; documented in the attribute).
- Internals/UntrackedDbContextDiscovery.cs:RegisterImplicitUsageSources
  — IL3050 suppression on MakeGenericType(DbContextUsageSource<>) over
  registered DbContext types (user DbContexts are preserved by their
  services.AddDbContext<T>() registrations).

Verification: full wolverine_slim.slnx builds clean (0 warnings /
0 errors on net9.0 + net10.0).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
….Newtonsoft

Merges origin/main into the chunk M branch to pick up the new
Wolverine.Http.Newtonsoft extension project (it was extracted from
Wolverine.Http during this PR's cycle) plus other recent main work,
and applies the chunk M annotation pattern to:

Wolverine.Http.Newtonsoft (1 site):
- CodeGen/NewtonsoftHttpCodeGen.cs:CreateWriteJsonFrame — IL2026
  suppression on MethodCall(NewtonsoftHttpSerialization,
  nameof(WriteJsonAsync)) at codegen time (target method statically
  referenced via nameof).

Wolverine.Polecat dedupe ambiguities (48 sites across 6 files —
symmetric to the Wolverine.Marten work in d215f72):

- IEventStream<>            : qualified with global::Polecat.Events
- IEventBoundary<>          : qualified with global::Polecat.Events.Dcb
- IEventOperations          : qualified with global::Polecat.Events

Files: AggregateHandling.cs, WriteAggregateAttribute.cs,
BoundaryModelAttribute.cs, UpdatedAggregate.cs,
Codegen/SessionVariableSource.cs, Codegen/LoadBoundaryFrame.cs.

Same dedupe-pillar transitional pattern as Marten side: once
Polecat 4 picks up JasperFx/polecat#103 (drops Polecat.Events.IEventStream,
Polecat.Events.Dcb.IEventBoundary, the Polecat.Events.IEventOperations
redeclaration), the bare references can replace the global:: qualifiers.

Verification:

    dotnet build wolverine_slim.slnx -c Release
    Build succeeded.
        0 Warning(s)
        0 Error(s)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jeremydmiller added a commit that referenced this pull request May 14, 2026
…checks

wolverine_slim.slnx omits several extension projects (Wolverine.EntityFrameworkCore,
Wolverine.Polecat, Wolverine.RavenDb, Wolverine.Http.Newtonsoft,
Wolverine.FluentValidation), so a clean slim build is not sufficient evidence
that a dependency-tightening change is clean across the repo. PR #2806's
chunk M annotation sweep hit this multiple times: each round of CI failures
exposed another extension project that the slim build didn't include. Recording
the lesson so future agents and contributors reproduce CI locally with the
full solution.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jeremydmiller added a commit to JasperFx/polecat that referenced this pull request May 14, 2026
Cuts the first alpha containing the dedupe-pillar adoption from PR #103:
- Polecat.Events.Protected.StreamCompactingRequest<T> dropped; consumers
  use the lifted JasperFx.Events.Protected.StreamCompactingRequest<T>.
- Polecat.Events.Dcb.IEventBoundary<T> dropped; consumers use the lifted
  JasperFx.Events.Tags.IEventBoundary<T>.
- Polecat.Events.IEventOperations redeclaration of FetchForWritingByTags<T>
  removed; inherited from JasperFx.Events.IEventStoreOperations.

Wolverine.Polecat downstream can drop the `global::Polecat.Events...`
qualifiers (introduced in JasperFx/wolverine#2806 as a transitional
disambiguation) once it pins this alpha.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
+ chunk M extension #5 (full-solution sweep)

Polecat 4.0.0-alpha.3 ships the dedupe-pillar adoption from
JasperFx/polecat#103: Polecat.Events.Dcb.IEventBoundary<T> and
Polecat.Events.IEventStream<T> are dropped (consumers use the lifted
JasperFx.Events.* counterparts). Wolverine.Polecat can now reference
those types unqualified.

Pin bump:
- Directory.Packages.props: Polecat 4.0.0-alpha.1 -> 4.0.0-alpha.3

Wolverine.Polecat (4 files) — revert global::Polecat.Events.IEventStream<>
and global::Polecat.Events.Dcb.IEventBoundary<> to bare references now
that alpha.3 dropped the duplicates. The Polecat.Events.IEventOperations
derived interface still exists (adds UnArchiveStream/TombstoneStream/
CompactStreamAsync) so those `global::Polecat.Events.IEventOperations`
qualifiers stay.

Source-code import fixes (the dropped Polecat types broke files that
imported `using Polecat.Events;` / `using Polecat.Events.Dcb;` — add the
new lifted-type namespace alongside):
- Wolverine.Polecat/Codegen/{BoundaryEventCapture,LoadAggregateFrame,
  MissingAggregateCheckFrame,RegisterEventsFrame}.cs +
  Persistence/Sagas/PolecatPersistenceFrameProvider.cs

Chunk M extension #5 — additional projects surfaced by `wolverine.slnx`
(CI's full-solution build target) that wolverine_slim.slnx omits:

Wolverine.AzureServiceBus.Tests/Samples.cs — pre-existing breakage on
main from PR #2808 (topic-per-tenant routing doc sample). Add missing
imports (ImTools, Wolverine.AzureServiceBus.Internal,
Wolverine.Configuration, Wolverine.Runtime, Wolverine.Runtime.Routing,
Wolverine.Runtime.Agents, JasperFx.Core.Reflection,
Microsoft.Extensions.DependencyInjection). This unblocks both my PR's
CI and main's currently-broken full-solution build.

Dedupe-pillar ambiguities in WebApi / test code:
- WolverineWebApi/Accounts/AccountCode.cs — qualify IEventStream<> with
  global::Marten.Events; ConcurrencyStyle with global::Wolverine.Marten
  (the WriteAggregate attribute expects the Wolverine-side enum).
- MartenTests/AggregateHandlerWorkflow/{aggregate_handler_workflow,
  strong_named_identifiers}.cs — same global::Marten.Events.IEventStream
  qualifier.
- PolecatTests/{Bugs/Bug_225,natural_key_aggregate_handler_workflow,
  AggregateHandlerWorkflow/strong_named_identifiers}.cs — add
  `using JasperFx.Events;` to resolve IEventStream<> after Polecat's
  alpha.3 drop.
- PolecatTests/AggregateHandlerWorkflow/polecat_command_workflow_middleware.cs —
  qualify ConcurrencyStyle with global::Wolverine.Polecat (matches the
  AggregateHandler attribute's enum type).

Verification: `dotnet build wolverine.slnx -c Release` succeeds with 0
errors on net9.0 + net10.0.

Once Marten 9 ships its lift adoption (JasperFx/marten#4403) the
`global::Marten.Events.*` qualifiers in this commit can be reverted
to bare references in a follow-up cleanup.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jeremydmiller added a commit that referenced this pull request May 14, 2026
Recast as fact ("CI builds X, pinned in .nuke/parameters.json") rather
than guidance, lead with the build command, and expand the list of
projects the slim solution omits — including the test projects
(AzureServiceBus.Tests, PolecatTests, MartenTests, WolverineWebApi) that
CI also compiles but slim does not. Also call out the dedupe-pillar
type-lift scenario as a concrete trigger alongside the AOT/trim case.

Captures the lesson from PR #2806's iterations: a clean slim build
masked CI-blocking compile errors several times during that PR's
chunk M sweep.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jeremydmiller and others added 6 commits May 14, 2026 16:40
…rten-side global:: qualifiers

Picks up the upstream packages that pair against the post-TPL-Dataflow-
removal JasperFx 2.0.0-alpha.13 + dedupe-pillar JasperFx.Events 2.0.0-
alpha.8:

- JasperFx.RuntimeCompiler  2.0.0-alpha.2 -> 5.0.0-alpha.1
- Marten                    9.0.0-alpha.1 -> 9.0.0-alpha.2
- Marten.AspNetCore         9.0.0-alpha.1 -> 9.0.0-alpha.2
- Marten.Newtonsoft         (new) 9.0.0-alpha.2

The Marten alpha.1 binary referenced the pre-removal 4-arg
RetryBlock<T>(..., Action<ExecutionDataflowBlockOptions>) ctor and was
binary-incompatible with the alpha.13 runtime — every DI resolution
that flowed into Marten.Events.EventGraph.Initialize raised
MissingMethodException. alpha.2 was rebuilt against alpha.13 and has
zero `System.Threading.Tasks.Dataflow` string references.

Marten alpha.2 dedupe-pillar adoption (JasperFx/marten#4403) drops
Marten.Events.Dcb.IEventBoundary<T>, Marten.Events.IEventStream<T>,
Marten.Events.IEventStoreOperations, and Marten.Events.StreamCompactingRequest<T>
in favor of the lifted JasperFx.Events counterparts. Reverted the
`global::Marten.Events.*` qualifiers I added in d215f72 /
0f0139e (transitional disambiguation while both products shipped
duplicates) back to bare references.

Cascade fixes surfaced by the alpha.2 API:

- `using JasperFx.Events;` added to Wolverine.Marten source +
  Wolverine.Marten test code that imported `using Marten.Events;`
  alone (which used to resolve IEventStream<> to Marten's duplicate;
  now resolves to the non-generic Marten.Events.IEventStream).
- `using JasperFx.Events.Tags;` added to files referencing
  IEventBoundary<> after Marten.Events.Dcb.IEventBoundary<> was dropped.
- Wolverine.Saga.Version widened from int to long to match
  Marten.Metadata.IRevisioned.Version (widened to long in alpha.2);
  cascaded the same widening to Saga subclasses that explicitly opt
  into IRevisioned (UserRegistrationSaga, SideEffects1,
  GpStreamAggregate, GSimpleAggregate).
- WolverineProjectionCoordinator<T> generic constraint tightened from
  `where T : IDocumentStore` to `where T : class, IDocumentStore` —
  Marten.Events.Daemon.Coordination.IProjectionCoordinator<T> now
  carries a `where T : class` constraint.
- HostExtensions / TestingExtensions methods constrained on
  `where T : IDocumentStore` similarly tightened to `class, IDocumentStore`.
- `using Marten.Newtonsoft;` (+ Marten.Newtonsoft package pin) added
  to MartenTests/Bugs/Bug_1427 — Marten alpha.2 extracted the
  Newtonsoft serialization extension methods to a separate package.
- Reverted leftover ConcurrencyStyle qualifier in
  MartenTests/AggregateHandlerWorkflow/marten_command_workflow_middleware.cs
  to global::Wolverine.Marten side (matches the AggregateHandler
  attribute's enum type).
- Tightened RegisterBoundaryEventsFrame<T> /
  ApplyBoundaryEventsFromAsyncEnumerableFrame<T> /
  RegisterEventsFrame<T> from `where T : notnull` to `where T : class`
  to satisfy IEventBoundary<T>'s / IEventStream<T>'s `class` constraints.

Local verification (per CLAUDE.md): full `dotnet build wolverine.slnx
-c Release` is clean (0 warnings / 0 errors on net9.0 + net10.0).
CoreTests: 1690/1692 passing; the 2 failures
(`system_message_type_filtering.observer_does_not_receive_message_routed_for_system_types`
× 2 TFMs) are pre-existing on main (run 25883603362) and unrelated to
this pin bump.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…iltering

- docs: add Saga.Version int->long row to the migration guide's "At a glance"
  table. The change tracks the IRevisioned.Version widening in Marten 9.0;
  typical user code is unaffected because int widens implicitly to long.

- test: system_message_type_filtering.observer_does_not_receive_message_routed_for_system_types
  was failing on main because PrepopulateRoutingCache (#2769) primes the
  router cache at startup. The post-startup RoutingFor calls were hitting the
  cache and skipping the Observer.MessageRouted hook entirely, so the
  observer recorded nothing. Clear the cache entries for the test's message
  types after swapping in the recording observer so the cache-miss path runs
  and the system-type filter around the observer hook is exercised.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Same root cause as the system_message_type_filtering fix in the prior
commit: PrepopulateRoutingCache (#2769) primes the router cache at host
startup against the default observer, so the post-startup swap to a
substituted observer followed by RoutingFor(typeof(M4)) hit the cache
and bypassed the Observer.MessageRouted call the test asserts on.

Clear the cache entry for M4 after wiring the substituted observer so
the cache-miss path runs and fires the hook. Grant InternalsVisibleTo
to MessageRoutingTests so it can call ClearRoutingFor (already granted
to CoreTests and several broker test projects).

Verified locally: MessageRoutingTests is 25/25 passing on net9.0 with
RabbitMQ running.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two fallout sites from widening Wolverine.Saga.Version from int to long
to track Marten 9's IRevisioned.Version widening:

1. src/Persistence/Wolverine.Marten/Persistence/Sagas/LoadDocumentFrame.cs
   The generated code emitted `var expectedSagaRevision = 0;` (inferred int)
   and then `expectedSagaRevision = saga.Version + 1;`. With Version now
   long, the assignment fails with `CS0266: Cannot implicitly convert type
   'long' to 'int'` and the whole runtime codegen for saga handlers blows
   up. Emit `0L` so the local is long.

   Surfaces as the two `MartenTests.Saga.When_handling_messages_in_saga.*`
   tests failing with "Compilation failures!" / CS0266.

2. src/Persistence/EfCoreTests/Optimistic_concurrency_with_ef_core.cs
   Test sets `Property("Version").OriginalValue = 999;` to fake a stale
   read. EF Core's concurrency-token comparator expects the boxed value's
   runtime type to match the property type. With Version now long, boxed
   int can't unbox to long and EF throws InvalidCastException before the
   expected DbUpdateConcurrencyException can bubble up as
   SagaConcurrencyException. Use `999L`.

   Surfaces as EfCoreTests.Optimistic_concurrency_with_ef_core.detect_concurrency_exception_as_SagaConcurrencyException
   failing with `InvalidCastException` instead of the expected
   `SagaConcurrencyException`.

Verified locally on net9.0 with PostgreSQL + SQL Server up:
- MartenTests.Saga.When_handling_messages_in_saga 4/4 passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PrepopulateRoutingCache (#2769) was added to warm the per-message-type
router cache at startup so the per-message RoutingFor() hot path never
pays the first-occurrence CloseAndBuildAs cost. It runs unconditionally
after the durability-mode-specific transport setup — which breaks two
restricted modes:

- MediatorOnly: no transports are started, but pre-populating still
  walks every message type and lazily materialises local sending
  agents through LocalRoutingMessageSource. That violates the mode's
  "no transports" contract and surfaces as
  PersistenceTests.Agents.durability_modes.mediator_does_not_start_any_transports
  failing with "agents.Any() should be False but was True".

- Serverless: RemoveLocal() strips the local transport, but
  MessageRouterBase<T>'s constructor unconditionally calls
  GetOrBuildSendingAgent(TransportConstants.DurableLocalUri) for
  scheduled-envelope fallback. With local removed, that throws
  UnknownTransportException during pre-population. Surfaces as
  PersistenceTests.Agents.durability_modes.start_in_serverless_mode
  failing with the same exception bubbling through host startup.

Gate the pre-population on Solo/Balanced modes only. The trade-off:
Serverless apps lose the AOT cold-start cache win temporarily — a
follow-up should make LocalDurableQueue lazy/nullable so Serverless
can opt back in. MediatorOnly never benefited (no runtime routing).

Verified locally on net9.0:
- PersistenceTests.Agents.durability_modes 7/7 passing.
- CoreTests 1692/1692 still passing (no regression).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The non-durable send_by_topics class already carries
[Trait("Category", "Flaky")] with an in-source explanation (#2618):
the topic-broadcast assertion races with RabbitMQ binding state and
reliably loses the second receiver when the test runs in the full
suite.

send_by_topics_durable runs the same broadcast pattern with Marten +
durable outbox state layered on top, which only widens the race
window. Its CI failures match the documented flake mode exactly —
`actual.Count should be 2 but was 1`, deterministic across the
workflow's two-attempt retry. Three tests trip it:
send_by_explicit_topic, send_by_explicit_topic_2, and
send_by_message_topic_to_multiple_listeners.

Skip via the same Flaky filter the sibling uses, pending the
deterministic topic-binding readiness gate tracked in #2618.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jeremydmiller
jeremydmiller marked this pull request as ready for review May 15, 2026 11:52
@jeremydmiller
jeremydmiller merged commit a8fb413 into main May 15, 2026
21 of 23 checks passed
jeremydmiller added a commit that referenced this pull request May 15, 2026
First alpha that consumes the post-#2806 critter-stack matrix:
JasperFx 2.0.0-alpha.13, JasperFx.Events 2.0.0-alpha.8,
JasperFx.RuntimeCompiler 5.0.0-alpha.1, Marten 9.0.0-alpha.2,
Polecat 4.0.0-alpha.3.

Updated the Directory.Build.props comment block to document the
alpha-by-alpha changelog so downstream consumers (CritterStackScalability
and the sample apps) can correlate their pin bumps with the upstream
scope.

NuGet publish is gated by manual workflow_dispatch on
.github/workflows/publish_nugets.yml — this commit only flags the
version on main; the maintainer triggers the publish when ready.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant