Skip to content

Wolverine 6.61.0

Latest

Choose a tag to compare

@jeremydmiller jeremydmiller released this 02 Nov 21:21
29806dd

This is a minor release. Upgrading is a package bump only: there is no schema change and no breaking API change.

New

  • GH-5320 (#5326): Recurring schedules can now run as often as every second, and a schedule can skip an occurrence while the previous one is still running.
    • CronSchedule.MinimumCadence is now one second, for six-field cron expressions such as * * * * * *. Anything faster than five seconds always runs on a timer agent, and UseScheduledMessages() refuses it.
    • The new SkipWhileRunning() on a recurring schedule invokes each occurrence instead of publishing it. An occurrence that comes due while the previous one is still running is skipped, and skipped occurrences are not made up later. Skips are logged and counted in the new wolverine-recurring-occurrences-skipped metric.
    • With a local handler, the occurrence runs on the node that owns the schedule's timer agent, so overlap is prevented across the cluster. Because the occurrence is invoked, other subscribers don't receive it, and it has no inbox row, queue error policy or dead letter queue. A failed occurrence is logged and the next one runs on schedule. With a handler on another node, the wait is capped at 5 seconds.
    • A one-second schedule writes about 86,400 deduplication rows a day.
  • GH-5317 (#5323): PauseThenCatchUpOnAllMartenDaemonActivityAsync() and the tracked-session option PauseThenCatchUpOnAllMartenDaemonActivity() catch up the main Marten store and every ancillary store registered with IntegrateWithWolverine() in one call. A store with no events is skipped.
  • GH-5311 (#5324): A failed handler attempt now records the OpenTelemetry exception event (exception.type, exception.message, exception.stacktrace) on its span, instead of only the exception's type name. Exception messages can carry application data, so you can turn this off with opts.Tracking.RecordExceptionsOnSpans = false.
  • GH-5339 (#5341): EntityDescriptor.Ddl now carries each EF Core entity's CREATE TABLE script, with its keys, foreign keys and indexes, the same way DocumentMappingDescriptor.Ddl does for documents. It's generated from the model, so no connection is opened, and it's the model's script rather than the database's. Non-relational providers and view-mapped entities leave it empty. Needs JasperFx 2.99.0.
  • GH-5332 (#5338): Wolverine HTTP endpoints now tag the request span with http.route and http.request.method, the OpenTelemetry semantic convention names, alongside handler.type. Both are constants in the generated code. Pre-generated code should be regenerated.
  • Dead letter queries can filter their time range on the failure time with the new DeadLetterEnvelopeQuery.RangeOn (DeadLetterTimeField.SentAt or FailedAt) (#5330). FailedAt falls back to sent_at when failed_at is null, and applies to query, replay, discard and archive. The default stays SentAt. Supported by the PostgreSQL, SQL Server, MySQL, SQLite, Oracle, CosmosDb and RavenDb stores.

Fixes

  • GH-5310 (#5328): With Marten's TrackConnections turned on, the handler, saga and stream tags (handler.type, message.handler, wolverine.saga.*, wolverine.stream.*) landed on the marten.connection span instead of the message's own span. They now stay on the message span, and on the request span for HTTP endpoints. Pre-generated code should be regenerated.
  • GH-5312 (#5327): A durable ScheduleRetry(...) lost the link to the attempt that failed, because the stored envelope body wasn't rewritten when the retry was scheduled. Every message store now rewrites the body when it reschedules an envelope.
  • GH-5313 (#5321): Azure Service Bus queues and subscriptions and Amazon SQS queues now report DeadLetterStorageMode.NativeWithRecovery when EnableDeadLetterQueueRecovery() drains them, so CritterWatch's startup check no longer warns about them.
  • GH-5314 (#5325): With RabbitMQ's EnableDeadLetterQueueRecovery(), stopping the host could throw AlreadyClosedException when two stops ran at once, as they do under WebApplicationFactory. Stopping the dead letter queue listener is now idempotent and never throws.
  • GH-5315 (#5322): FindSingleTrackedMessageOfType<T>() now counts envelopes rather than distinct message values, so publishing two equal records fails the check. A message sent to several destinations still counts once. Use tracked.Sent.SingleMessage<T>() for a check per destination.
  • GH-5318 (#5319): The testing docs now explain that the pause in PauseThenCatchUpOnMartenDaemonActivity waits out the high water agent's current poll tick. The fix is JasperFx/jasperfx#1100.
  • GH-5331 (#5336): With runtime code generation, each saga message disappeared from ServiceCapabilities.Sagas once it had been handled, and the saga disappeared once every message had been. The saga report, including each store's GetRegisteredSagasAsync, now reads the same before and after the chains compile.
  • GH-5334 (#5337): In Balanced mode, lifting a pause on a URI that no agent owns, such as a listening endpoint, waited out AgentRestrictionConfirmationTimeout and then threw AgentRestrictionsNotConfirmedException. It now returns at once. Agent URIs are still confirmed as before.
  • Sessions the application opens itself and enrolls with IPolecatOutbox.Enroll or IFisherOutbox.Enroll never flushed their outgoing messages on commit (#5309). Durable messages waited until a restart and buffered messages were lost. They now flush on commit, the same as handler sessions, and the incoming envelope is marked handled once instead of twice.

Dependencies

  • JasperFx 2.99.0 (#5333 took 2.98.0, #5341 2.99.0).
  • Weasel 9.48.0 and MySqlConnector 2.6.1 (#5335). MySqlConnector 2.6.1 closes GHSA-473q-m89c-ghf8 for WolverineFx.MySql. On SQL Server, a DateTime parameter in a message store command now goes out as datetime2 instead of datetime. Every envelope time column is datetimeoffset, so no column is converted either way.

Thanks to @uniquelau for #5313, #5314, #5315, #5317 and #5318, and to @lahma for #5330.

Full Changelog: V6.60.0...V6.61.0