Wolverine 6.44.0
This release came overwhelmingly from outside the core team. Six people outside JasperFx reported or fixed
the work in it, including three who sent the pull request themselves, and one report that reconstructed a
production cluster failure in enough detail to find two defects nobody had suspected.
Thank you
| @alesdvorakcz (Aleš Dvořák) | Found and fixed the EF Core mark-as-handled identity bug (#4703 / GH-4701) — a fanned-out message under MessageIdentity.IdAndDestination had every destination's inbox row retired by the first handler to commit, losing the copies whose handlers had not run, with no dead letter and no log. Also reported GH-4704. |
| @ayuksekkaya (Ali Yuksekkaya) | Two OpenAPI accuracy PRs (#4722, #4724) and the ten-variant reproduction behind GH-4712 — declaratively loaded entities that were never saved. |
| @thomhurst (Tom Longhurst) | Found and fixed GH-4729 (#4730): Azure Service Bus dead-letter moves passed a null propertiesToModify, so poison messages silently never reached $DeadLetterQueue. Bisected across 27 releases and identified why the existing tests were blind to it. |
| @erdtsieck | GH-4718 — see below. One of the best bug reports this project has received. |
| @net0well | GH-4699: TypeLoadMode.Static ignored DisableConventionalDiscovery(). |
| @alexandrefresnais | GH-4700: a scheduled retry ran on a node that does not own the partition slot. |
The agent control queue stall (GH-4718)
@erdtsieck reported 5.4–6.7 MB agent commands being rejected on a sharded multi-tenant cluster — 512
databases, ~2,200 tenants, 37,000–58,000 agents — alongside agent assignment stalling for 30–60 minutes
after every node change, and explicitly marked the causal link between the two as a hypothesis rather than
a finding. It held, and the report's detail is what made both halves findable:
- Stops were the one agent command never chunked. Starts and reassignments chunk by
AgentStartBatchSize; stops took a destination's whole set in one envelope. A node shedding 7,592 agents
emitted a single ~6 MB command that the destination refuses to read at all. This is also why lowering
AgentStartBatchSizechanged nothing — that knob had never touched the stop path. - One unreadable control queue row killed a node's entire control queue. The poller and the
expired-row cleanup share one transaction, so the failed read rolled back the very expiry that would have
cleared the offending row. The node then re-read it every poll and received no control message at all,
which is why the leader reported "confirmed 0 of N" for chunk after correctly-sized chunk. - Both halves now name themselves in the logs — the row, its message type, its size and the node it was
addressed to.
Fixes
- GH-4701 / GH-4705 — mark-as-handled inside the caller's transaction now matches the whole inbox
identity rather than the id alone, on EF Core (#4703) and on Marten, Polecat and Fisher (#4725). Both
also pick up the partition-aware statement, so a redelivered row can be retired under
EnableInboxPartitioning. - GH-4712 / GH-4717 — an entity loaded through
[Entity],[All],[FirstOrDefault],[Queryable]
or a query plan now enrolls the transaction. Mutating one and relying on the transactional middleware
previously saved nothing at all, on EF Core with no diagnostic. GH-4717 closes the same gap for every
other provider. - GH-4718 — see above.
- GH-4729 — Azure Service Bus dead-letter moves no longer pass a null
propertiesToModify. - GH-4700 — a promoted scheduled retry is settled by partition slot ownership rather than by whether
the promoting node happens to be able to build a local circuit. - GH-4699 — the static handler registry honors
DisableConventionalDiscovery(). - GH-4716 —
[Transactional]no longer reports a chain as transactional when no provider claimed it
and no transaction was applied. HTTP endpoints affected by this stop advertising a 409 they cannot raise.
New
TrackedSessionConfiguration.IgnoreEnvelopes(Func<Envelope, bool>)(GH-4704) — scope a tracked
session by anything on the envelope, not just by message type. For shared hosts where the same message
type is legitimately in flight for more than one reason at once.Durability.CompressAgentCommands(GH-4720, off by default) — gzip agent command payloads under
their ownbinary/wolverine+gzipcontent type. Measured 3.9x–24x on realistic agent URI lists. Turn it
on only once every node in the cluster runs a version that can read it; reading works from this version
forward.- GH-4702 — a startup warning for a plural-named
...Handlers/...Consumersclass whose handler
methods conventional discovery never picked up.
Worth knowing before upgrading
- GH-4714 regenerates committed generated code once. Continuation variables in generated handlers were
numbered from a process-wide static counter, so adding an unrelated DI registration renumbered dozens of
files. They are numbered per chain now and the names stop moving — but the first regeneration after
upgrading will drop the numeric suffixes. - GH-4716 and GH-4717 change which chains report
IsTransactional. Both corrections, but if you have
a policy or OpenAPI filter keying on that flag, its answer changes for chains that were previously
reporting it wrongly in either direction.