Wolverine 6.23.0
Projection & agent distribution
TL;DR: this prevents Wolverine from going into a panic doing agent assignments and churning crazily hard during Kubernetes rollouts or cluster starts and that's a very good thing
The bulk of this release. A wave of fixes (WO-1..8) to the agent assignment plane that together remove the re-assignment churn and livelock that could leave projection agents flapping or wedged.
- Node heartbeats no longer block behind command execution (#3620)
- Node resurrection restores the node's real identity rather than a skeleton record (#3621)
- A pending-assignment ledger suppresses duplicate
AssignAgentfloods (#3622) - Agent batch starts are chunked and bounded-parallel, so they stay safe at scale (#3623)
- Ejection hysteresis plus leader protection (#3624)
- The assignment row is re-upserted for agents that are already running (#3619)
- Local agents drain with bounded parallelism on shutdown (#3636)
- Paused shards now say why.
IEventSubscriptionAgent.Failuresurfaces aShardFailure— category, the failing event's sequence and type, and the root exception type — through health checks and a newIWolverineObserver.AgentPausedhook plus aNodeRecordType.AgentPausedrecord. Failures bound to a specific event (ApplyEvent,EventSerialization,UnknownEventType) or to two processes racing one shard (ProgressionOutOfOrder) are no longer auto-restarted, since they would die on the identical event every time (#3637, #3638) - Agent starts retry locally, bounded by
Durability.AgentStartRetryAttempts/AgentStartRetryDelay, instead of idling a fullCheckAssignmentPeriodafter a startup race (#3519) - Store-scoped
FindAgentUriAsyncoverload (#3647) and a store-awareTryRebuildRegisteredProjectionAsyncoverload (#3618)
Bumps JasperFx.Events to 2.36.1, Marten to 9.20.0 and Polecat to 5.7.0.
HTTP
- Endpoints that advertise a request body their HTTP method cannot carry now fail fast at startup instead of silently 404ing out of the route matcher (#3648)
- A missing
Content-Typeon an[AcceptsContentType]route returns 415 rather than 404 (#3649) - Query-only
[AsParameters]endpoints no longer advertise a form body, which had been dropping them from route matching entirely (#3630) - Explicitly-routed chains —
PublishMessage<T>andSendMessage<T>— now describe the message they read from the body. They had been advertising no request body at all in OpenAPI (#3646) - Enum values in query strings and form posts parse case-insensitively (#3629)
- Compiled queries returned as a Wolverine.Http resource no longer execute twice (#3625)
Transports
- Conventional routing respects named brokers (#3633)
- Google Pub/Sub: named-broker support for sharded and partitioned topics (#3632), and
ListenToPubsubSubscriptionOnNamedBroker(#3631) - Kafka: topic-already-exists error codes are handled rather than thrown (#3640)
- Redis: scheduled retries survive an unreadable timestamp (#3613), and scheduled entries that repeatedly fail to deserialize are dead-lettered instead of looping (#3644)
EnvelopeMapperreads both timestamp header formats (#3645)- NServiceBus interop: the
EnclosedMessageTypesheader is split before the message type is resolved, so interop works across Azure Service Bus, SNS, SQS and the database transports (#3628)
Persistence
- Oracle runs the durability agent through the shared batching mechanics (#3614). Note that ODP.NET exposes no
DbBatch, so the work splits per statement.
Other
- Resource discovery no longer eager-connects broker transports (#3617)
Contributors
Thank you to everyone who contributed to this release:
- @bittercoder — Alex Henderson (#3631)
- @Gwynbleid85 — Miloš Hegr (#3640)
- @jeremydmiller — Jeremy D. Miller
- @outofrange-consulting — Geoffrey Marc (#3629)
- @pedroandrade03 — Pedro Henrique Andrade Siqueira (Oracle durability batching, #3614)
- @uniquelau — Laurence Gillian (#3617, #3625)
Full changelog: V6.22.0...V6.23.0