Skip to content

Wolverine 6.44.0

Choose a tag to compare

@jeremydmiller jeremydmiller released this 30 Sep 23:14
1ad0b03

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
    AgentStartBatchSize changed 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 own binary/wolverine+gzip content 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 / ...Consumers class 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.