Skip to content

Bump WolverineFx from 6.23.0 to 6.24.0 - #112

Closed
dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/nuget/WolverineFx-6.24.0
Closed

Bump WolverineFx from 6.23.0 to 6.24.0#112
dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/nuget/WolverineFx-6.24.0

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Jul 29, 2026

Copy link
Copy Markdown
Contributor

Updated WolverineFx from 6.23.0 to 6.24.0.

Release notes

Sourced from WolverineFx's releases.

6.24.0

Two data-loss fixes — but for unusual usages

This release closes two bugs that silently destroyed data rather than failing loudly. Both are worth reading before you skip the rest of these notes.

Durable inbox rows were orphaned when a circuit breaker tripped (#​3680). DurableReceiver checked its latched flag before calling MarkReceived. The latched path still persists each envelope to the inbox as a safety net — but on an envelope that never went through MarkReceived, Status is the enum default (Outgoing) and Destination is null. Both are filter columns for inbox recovery, so the rows were written in a state no recovery sweep on any node could ever see. The null Listener also skipped the nack back to the broker, and the broker's redelivery after restart hit DuplicateIncomingEnvelopeException — which acks and drops. Net result: genuine message loss under a durable inbox any time a circuit breaker trip latched the receiver mid-flight. Measured on the circuit-breaker suite, 9 of 1,200 messages were lost per run.

Dropping one tenant from a shared partition bucket destroyed its co-tenants' data (#​3686). Found alongside #​3683. Tenant bucketing — registering several small tenants against one partition suffix so they share a physical partition — is documented and exposed through PartitionPerTenant(p => p.AllowPartitionSharing = true), and it did not work on either engine. It had no test coverage, because the doc sample demonstrating it is compile-only and never executed.

Global partitioning

Part of the GlobalPartitioning epic (#​3482).

  • Global partitioning topologies for PostgreSQL and SQL Server queues (#​3468, #​3469)
  • End-to-end sharded-processing suites for Azure Service Bus, GCP Pub/Sub, NATS, Redis Streams and Pulsar (#​3467). The scenario is lifted into Wolverine.ComplianceTests.Partitioning.ShardedProcessing, so a new transport costs one small test class
  • Native-mode design comparison and per-transport native alternatives documented (#​3481)

The new suites immediately found two real bugs:

  • NATS global partitioning had never worked at all. The topology forces EndpointMode.Durable on every slot, and a NatsEndpoint only supports Durable when JetStream-backed — so every UseShardedNatsSubjects() call threw at configuration time. The topology now enables JetStream on its own endpoints and declares a work-queue stream per shard, without which the listener died at startup on stream not found
  • Pulsar named its companion local queues off the full topic path, producing queues like global-persistent://public/default/orders1. They now use the topic's short name, matching every other transport

Multi-tenancy and persistence

  • EF Core tenant partition back-fill (#​3496). Routine migration deltas deliberately leave Weasel-managed partitions alone, so a table joining an existing managed set — a newly deployed service, or a newly mapped ITenanted entity — had no partition for any tenant registered before that table existed. IConjoinedTenantPartitions<T>.MigrateTenantPartitionsAsync() reconciles every partitioned table against the full registered tenant set, with per-table TenantPartitionResult reporting
  • Conjoined tenant partition bucketing actually works now, on both PostgreSQL and SQL Server (#​3683, and see #​3686 above)
  • Exclusive listener inbox recovery is now covered for RavenDb (#​3595) and CosmosDb (#​3596)

Transports

  • RabbitMQ: deliveries are settled against the channel they arrived on (#​3687). Acking a delivery on a torn-down channel threw a NullReferenceException
  • NATS: auto-provisioned JetStream durable consumers are filtered to their own subject (#​3676). FilterSubject was only assigned when ConsumerName was empty, so every durable consumer on a stream received every message. The fix needs a FilterSubjects multi-filter — a single filter cannot cover both {subject} and {subject}.scheduled, and a work-queue stream discards an uncovered control message
  • MQTT: the v5 authentication method name is configurable (#​3588). It was hardcoded to "OAUTH2-JWT". Azure Event Grid's custom JWT authentication requires CUSTOM-JWT, so those brokers could not be reached through Wolverine's authentication support at all. You could already set the method by hand through MqttClientOptionsBuilder.WithAuthentication(), but that gave up Wolverine's token refresh loop — the whole reason to use MqttJwtAuthenticationOptions. You no longer have to choose
  • The HTTP transport can send to a destination nobody pre-registered (#​3681, reported as ProductSupport#​34). WolverineHttpTransportClient used the endpoint's OutboundUri purely as an IHttpClientFactory client name, then posted to that client's BaseAddress — so operator commands sent back over the HTTP transport failed with An invalid request URI was provided

Performance

  • RabbitMQ consumer dispatch concurrency is now per-endpoint (#​3492). The client default of 1 was the bottleneck. Simulated handler, 2,000 msg/s offered load, 30s measured window:

    ConsumerDispatchConcurrency Throughput Transit p50
    1 (client default) 163.7/s — (nothing from the measured window was consumed before the run ended)
    5 828/s 22,871.9 ms
    20 1,999.1/s 1.486 ms (p95 2.54, p99 3.22)

    The 5.1x and 12.2x multiples understate it — at 1 and 5 the listener never catches up at all.

  • Amazon SQS batches message deletions and chunks outgoing batches on the 256KB request size limit (#​3493)

  • Azure Service Bus session listeners are no longer quadratic — the n² session loops are now n. MaxConcurrentCalls is surfaced, and a batched defer settles the original message (#​3494)

HTTP and gRPC

... (truncated)

6.23.1

Agent distribution

TL;DR: if you pause a projection from CritterWatch on 6.23.0, restarting it appears to do nothing for a full minute. This fixes that.

  • A paused projection or subscription agent now resumes immediately when you restart it (#​3663). On 6.23.0 the restart was accepted, the pause restriction was cleared, and then nothing happened until the pending-assignment ledger's TTL expired — 2 × CheckAssignmentPeriod, so 60 seconds with the defaults. Long enough that an operator reasonably concludes the agent is never coming back.

    The ledger introduced in 6.23.0 (#​3622) only counted an assignment as confirmed if a later evaluation saw the agent running and still assigned to the same node. A pause makes those two conditions mutually exclusive: the first evaluation that can observe the delivered assignment is the same one that detaches the agent. The entry was never confirmed, nothing on the stop path cleared it, and the restart's AssignAgent was suppressed as a duplicate still in flight. Delivery alone now confirms the entry, which is the only question the ledger was ever asking.

  • Pausing an agent no longer briefly starts it first (#​3666). ApplyRestrictionsAsync kickstarted a health check before persisting the operator's restriction change, so that evaluation ran against the old restrictions and could act against the very intent being applied — for a pause, re-assigning and starting the agent one beat before the merged evaluation stopped it again. Besides the wasted daemon start/stop cycle, this is what armed the stale ledger entry behind #​3663.

PostgreSQL

  • Advisory-lock sessions stay invisible to Marten's async-daemon gap detection (#​3664). Marten 9.16.1+ will not skip a stale event-sequence gap while any session whose open transaction predates that gap is still alive (marten#​4953). A session parked in an open transaction for the life of the process therefore reads as a permanent "possible reserver" and can hold the high-water mark — and every async projection — behind a gap that is genuinely dead.

    Wolverine's long-held locks were already shaped correctly: leader election and node coordination hold session-scoped advisory locks on a dedicated connection with no transaction, so they show up as state='idle' with a NULL xact_start. Those sessions are now also tagged application_name = 'wolverine-advisory-lock:<database>', which turns a pg_stat_activity investigation from guesswork into something you can read at a glance. The constraints are pinned in tests and in the Postgres durability docs, including the trap worth knowing in your own code: never add a keepalive query inside a long-lived open transaction — it bumps state_change, makes the session look active, and re-promotes it to candidate reserver.

    Note for combined Marten + Wolverine deployments: older guidance suggested Postgres's idle_in_transaction_session_timeout as a dead-gap backstop. Prefer upgrading Marten and using SkipStaleGapsDespiteLiveTransactionsAfter instead.

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.24.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 Jul 29, 2026
@dependabot @github

dependabot Bot commented on behalf of github Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #113.

@dependabot dependabot Bot closed this Jul 29, 2026
@dependabot
dependabot Bot deleted the dependabot/nuget/WolverineFx-6.24.0 branch July 29, 2026 04:14
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