Repository navigation
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.MinimumCadenceis now one second, for six-field cron expressions such as* * * * * *. Anything faster than five seconds always runs on a timer agent, andUseScheduledMessages()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 newwolverine-recurring-occurrences-skippedmetric. - 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 optionPauseThenCatchUpOnAllMartenDaemonActivity()catch up the main Marten store and every ancillary store registered withIntegrateWithWolverine()in one call. A store with no events is skipped. - GH-5311 (#5324): A failed handler attempt now records the OpenTelemetry
exceptionevent (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 withopts.Tracking.RecordExceptionsOnSpans = false. - GH-5339 (#5341):
EntityDescriptor.Ddlnow carries each EF Core entity'sCREATE TABLEscript, with its keys, foreign keys and indexes, the same wayDocumentMappingDescriptor.Ddldoes 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.routeandhttp.request.method, the OpenTelemetry semantic convention names, alongsidehandler.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.SentAtorFailedAt) (#5330).FailedAtfalls back tosent_atwhenfailed_atis null, and applies to query, replay, discard and archive. The default staysSentAt. Supported by the PostgreSQL, SQL Server, MySQL, SQLite, Oracle, CosmosDb and RavenDb stores.
Fixes
- GH-5310 (#5328): With Marten's
TrackConnectionsturned on, the handler, saga and stream tags (handler.type,message.handler,wolverine.saga.*,wolverine.stream.*) landed on themarten.connectionspan 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.NativeWithRecoverywhenEnableDeadLetterQueueRecovery()drains them, so CritterWatch's startup check no longer warns about them. - GH-5314 (#5325): With RabbitMQ's
EnableDeadLetterQueueRecovery(), stopping the host could throwAlreadyClosedExceptionwhen two stops ran at once, as they do underWebApplicationFactory. 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. Usetracked.Sent.SingleMessage<T>()for a check per destination. - GH-5318 (#5319): The testing docs now explain that the pause in
PauseThenCatchUpOnMartenDaemonActivitywaits 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.Sagasonce it had been handled, and the saga disappeared once every message had been. The saga report, including each store'sGetRegisteredSagasAsync, now reads the same before and after the chains compile. - GH-5334 (#5337): In
Balancedmode, lifting a pause on a URI that no agent owns, such as a listening endpoint, waited outAgentRestrictionConfirmationTimeoutand then threwAgentRestrictionsNotConfirmedException. It now returns at once. Agent URIs are still confirmed as before. - Sessions the application opens itself and enrolls with
IPolecatOutbox.EnrollorIFisherOutbox.Enrollnever 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, aDateTimeparameter in a message store command now goes out asdatetime2instead ofdatetime. Every envelope time column isdatetimeoffset, 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