Skip to content

Bump WolverineFx from 6.29.2 to 6.31.0 - #334

Merged
github-actions[bot] merged 1 commit into
mainfrom
dependabot/nuget/benchmarks/Foundatio.Mediator.Benchmarks/WolverineFx-6.31.0
Sep 7, 2026
Merged

github-actions[bot] merged 1 commit into
mainfrom
dependabot/nuget/benchmarks/Foundatio.Mediator.Benchmarks/WolverineFx-6.31.0

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Sep 7, 2026

Copy link
Copy Markdown
Contributor

Updated WolverineFx from 6.29.2 to 6.31.0.

Release notes

Sourced from WolverineFx's releases.

6.31.0

Logical message deduplication

Envelope.Id identifies one delivery. That is the right identity for "the broker handed me this twice" and the wrong one for "the operator clicked Rebuild twice" — those are different deliveries of the same intent, so each carries a different Envelope.Id and every one gets through.

6.31.0 promotes Envelope.DeduplicationId into a first-class logical id, with storage, enforcement, and a retention policy behind it.

opts.Durability.EnableMessageDeduplication = true;   // provisions wolverine_deduplication
opts.Durability.DeduplicationWindow = 24.Hours();    // this IS the guarantee

[Deduplicated]
public static void Handle(RebuildProjection command) { }

It is opt-in throughout — leaving it off means no schema change at all on upgrade. Storage is a separate wolverine_deduplication table rather than a column on the inbox, because under EnableInboxPartitioning the inbox is PARTITION BY LIST (status) and marking an envelope handled moves the row between partitions, which would let one logical id exist as both Incoming and Handled — silently, and only for users who enabled partitioning. Claiming is an INSERT that either succeeds or trips the primary key, never a SELECT-then-INSERT.

Refusals differ per chain type: a message handler discards and acks, HTTP returns 409 with ProblemDetails (configurable to 2xx where a replay is benign), gRPC returns AlreadyExists / InvalidArgument per AIP-193. Storage on PostgreSQL, SQL Server, MySQL and SQLite.

Deriving the id from the message

The publishing side does not have to remember DeliveryOptions.DeduplicationId at every call site. A message type declares its own logical identity once, the way it already declares a topic name with [Topic] or a saga id with [SagaIdentity]:

public record ArchiveInvoice([property: DeduplicationIdentity] string InvoiceNumber, DateOnly AsOf);

[DeduplicationIdentity(nameof(ReceiveShipment.ShipmentId))]   // a contract whose members you cannot decorate
public record ReceiveShipment(Guid ShipmentId, string Warehouse);

// or configured, for composed ids and generated message types
opts.MessageDeduplication.ByMessage<RebuildProjection>(x => $"{x.ProjectionName}|{x.OccurrenceUtc:O}");
opts.MessageDeduplication.ByMemberNamed("IdempotencyKey", "DeduplicationId");
opts.Policies.ForMessagesOfType<CreateOrder>().DeduplicateBy(x => $"{x.Sku}|{x.Quantity}");

These are IEnvelopeRule at the message type level, resolved once when the route is built rather than per message. An explicit DeliveryOptions.DeduplicationId always wins, then configured rules, then the attribute.

Fixes

  • Broker startup is bounded by a clock. A host starting against a dead broker took 21m38s to fail — long enough to look like a hang and to blow past any orchestrator's startup probe. (#​4116)
  • ListeningAgent sees past its receiver wrappers. ReceiverWithRules — installed by a bare endpoint-level MessageType or TenantId — is unconditionally an ILocalQueue, so a wrapped NativeAck or Inline receiver took the wrong branch and threw on the durability agent's re-entry path. The same blindness meant a terminally faulted receiver reported healthy forever on exactly the endpoints most likely to be non-trivially configured. (#​4188, #​4191)
  • A locally-owned shard that stopped with nothing to report is restarted. It was invisible to both recovery paths because each deferred to the other; the status was correct, the assignment was correct, and nothing joined the two. Reached through the console's Rebuild, which completed, acked success, and left the shard dead. (#​4193)
  • A NativeAck or Inline listener reports its real queue depth and last receipt instead of 0. (#​4186)
  • Event Model derivation stops claiming TriggerLabel, which was beating overlay declarations and minting a SourceDisagreement hotspot per labelled route; and a collection response now reads its element type instead of reporting an assembly-qualified CLR string as a canvas node. (#​4181, #​4182)
  • An agent command is never forwarded to the node it is already on. (#​4184)

Dependencies

  • JasperFx, JasperFx.Events and the two source generator packages to 2.57.2.

Full changelog: JasperFx/wolverine@V6.30.3...V6.31.0
... (truncated)

6.30.3

Patch release. Requires JasperFx 2.57.1, which ships the code-generation half of two of these fixes.

Several of these failed silently — a host that started clean, passed health checks, and did less than it appeared to. Worth a look if any of the shapes below match your application.

Code generation and service location

  • ServiceProviderSource.IsolatedAndScoped is now honored by Wolverine.HTTP (#​4171). An endpoint or middleware asking for an IServiceProvider always received httpContext.RequestServices, whatever you configured. Note the consequence: asking for an IServiceProvider in an endpoint is service location and now registers as such, so under ServiceLocationPolicy.NotAllowed those endpoints will throw where they previously slipped past the policy unnoticed. Message handlers have always behaved this way.

  • Scope priming now fires for every chain that service-locates, not only those naming an IServiceProvider (#​4171). If a chain reached service location solely through an opaque scoped/transient registration, its child scope was never primed — so a service-located IMessageContext, IMessageBus, or Marten IDocumentSession was a second, un-enrolled instance rather than the one the handler already owned. Handlers and HTTP endpoints are both covered now.

  • Lazy<T> dependencies resolve through their registration (#​4159). An open-generic registration such as TryAddScoped(typeof(Lazy<>), typeof(LazyResolver<>)) was ignored whenever the closed type was itself concrete, and new Lazy<IFoo>() was emitted instead. That compiles and can never work — the first .Value throws MissingMemberException for any service without a public parameterless constructor. Relatedly, AlwaysUseServiceLocationFor(typeof(Lazy<>)) accepted an open generic and then matched nothing; it now matches that generic's closed forms.

Sagas

  • ResequencerSaga advances LastSequence when a message is handled, not when it is published (#​4172). A replayed message could let a queue backlog walk past the ordering guard while it was still in flight, reordering the handled sequence.

  • An already-sequenced arrival is observable and overridable (#​4175). A message whose order the saga had already passed was handled again in silence. The new shouldHandleAlreadySequenced hook logs a warning by default — behavior is unchanged — and can be overridden to discard, raise a metric, or throw.

Startup

  • AutoCreate.None no longer pays for a full schema diff at startup (#​4166).

Full changelog: JasperFx/wolverine@V6.30.2...V6.30.3

6.30.2

This addresses an issue encountered by a JasperFx client hitting a sudden crunch of messages being enqueued into local queues. Not something we expect to be common at all, but now we're better anyway!

What's Changed

Full Changelog: JasperFx/wolverine@V6.30.1...V6.30.2

6.30.1

There's some CritterWatch related functionality smuggled in here for our forthcoming Event Modeling visualization. Otherwise, this is mostly a ton of fine grained improvements for CI or message broker usage problems detected by dogfooding and some "Mr. AI tool, go try to identify potential problems" action

What's Changed

Full Changelog: JasperFx/wolverine@V6.30.0...V6.30.1

6.30.0

Wolverine 6.30.0 is a large release built around one headline feature — a new endpoint mode — plus the usual crop of transport fixes, and a couple of long-standing multi-tenancy and HTTP gaps closed.

EndpointMode.NativeAck

The main event. Buffered's throughput and partitioning with Inline's no-loss guarantee, and no database required.

A broker delivery is held unacknowledged while the envelope flows through an in-memory, optionally group-partitioned execution block, and is settled natively when the handler pipeline terminates. Nothing is acknowledged ahead of its handler, so work parked in a lane when a node goes away comes back rather than vanishing.

opts.ListenToRabbitQueue("orders")
    .ProcessInParallelWithNativeAcks();

The guarantee, stated exactly: no two messages sharing a group id execute concurrently. Ordering is per-slot best-effort, not per-group guaranteed; redelivery may reorder. Anything needing strict order under failure keeps the durable inbox.

Transport support is opt-in and default-closed — a transport must explicitly claim the mode, because most settlement models cannot express out-of-order completion. Adopted by RabbitMQ, Amazon SQS, Azure Service Bus, NATS JetStream, Redis Streams, Pulsar and GCP Pub/Sub (#​3708, #​4046, #​4047, #​4050, #​4051, #​4052, #​4053).

Supporting work in the same wave:

  • Lease renewal for queued envelopes on clocked transports — SQS, ASB, JetStream and Pub/Sub run a clock on an unsettled delivery, and the risk window is lane queue time plus handler time (#​4048).
  • In-memory idempotency guard, an opt-in duplicate filter for a mode with no inbox row to deduplicate against (#​3710).
  • Global partitioning across sharded queues (#​3709).
  • Listener mode coherence validation, which caught that RabbitMQ queues default to Inline — so sharded topologies were silently unpartitioned without an explicit BufferedInMemory() (#​3712, #​4022).
  • A five-node chaos reproduction under webhook flood, measuring the real duplicate rate on abrupt node loss (#​3713).

Multi-tenancy

  • Conjoined EF Core tenancy now works when Marten owns the message store via IntegrateWithWolverine(). Marten hands Wolverine an NpgsqlDataSource rather than a connection string, and NpgsqlDataSource.ConnectionString deliberately omits the password — so there is a new DbDataSource overload of AddDbContextWithWolverineManagedConjoinedTenancy that carries credentials through intact. A second defect on the same path is fixed too: IntegrateWithWolverine() never registered the tenant partitioning provider, so PartitionPerTenant() failed (#​4044).

HTTP and event sourcing

  • [StreamState] and [StreamEvents] — new parameter attributes for handlers whose read is the raw stream rather than the folded aggregate, for timeline and audit shaped endpoints that [ReadModel] cannot express. Store-agnostic across Marten, Polecat and Fisher; Marten batches both fetches into a single round trip (#​3627).
  • Marten concurrency conflicts as 409 — a documented, tested recipe for mapping optimistic-concurrency failures on [WriteAggregate] endpoints to ProblemDetails instead of an unhandled 500. Note that StreamLockedException derives from MartenException, not ConcurrencyException, so catching only the latter silently leaves FetchForExclusiveWriting returning 500s (#​3764).
  • Event Model slices per route — HttpChainDescriptor and GrpcRpcDescriptor now carry the slice the route is, so a consumer walking endpoint by endpoint sees it next to the route rather than only through the assembled model (#​4000).

Transport fixes

  • Pulsar: requeue, scheduled retry and dead-letter routing implemented (#​3797). A global failure rule was silently disabling every user error policy application-wide (#​4075). Hot-tail listeners silently dropped deferred messages in every mode (#​4060).
  • GCP Pub/Sub: listener shutdown could hang on in-flight callbacks (#​4065); exhausting MaxTotalAckExtension silently delivered a concurrent duplicate rather than reporting anything (#​4066); effective listener concurrency was not what the configuration implied, and the flow-control bound is global per SubscriberClient rather than per inner client (#​4067). PubsubTopicOptions.OrderBy gained a configuration surface (#​4087).
  • Redis: DeleteStreamEntryOnAck silently never acked on Redis < 8.2, where XACKDEL is unsupported (#​4058).
  • Ack reliability: a shared ack-attempt budget across stacked retry blocks, and terminal-failure classification for Azure Service Bus and SQS so a permanent settle failure stops rather than burning the whole budget (#​4012).

Upgrading

Additive. EndpointMode.NativeAck is opt-in per endpoint and default-closed per transport, and MaximumBrokerRedeliveries defaults to off. Requires JasperFx 2.55.0.

Commits viewable in compare view.

Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options

You can trigger Dependabot actions by commenting on this PR:

  • @dependabot rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency
  • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)

---
updated-dependencies:
- dependency-name: WolverineFx
  dependency-version: 6.31.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot dependabot Bot added .NET Pull requests that update .NET code dependencies Pull requests that update a dependency file labels Sep 7, 2026
@github-actions
github-actions Bot merged commit a148013 into main Sep 7, 2026
3 checks passed
@github-actions
github-actions Bot deleted the dependabot/nuget/benchmarks/Foundatio.Mediator.Benchmarks/WolverineFx-6.31.0 branch September 7, 2026 22:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file .NET Pull requests that update .NET code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants