Skip to content

Wolverine 6.23.0

Choose a tag to compare

@jeremydmiller jeremydmiller released this 27 Jul 00:30
fe74ab4

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 AssignAgent floods (#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.Failure surfaces a ShardFailure — category, the failing event's sequence and type, and the root exception type — through health checks and a new IWolverineObserver.AgentPaused hook plus a NodeRecordType.AgentPaused record. 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 full CheckAssignmentPeriod after a startup race (#3519)
  • Store-scoped FindAgentUriAsync overload (#3647) and a store-aware TryRebuildRegisteredProjectionAsync overload (#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-Type on 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> and SendMessage<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)
  • EnvelopeMapper reads both timestamp header formats (#3645)
  • NServiceBus interop: the EnclosedMessageTypes header 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:

Full changelog: V6.22.0...V6.23.0