| Name | Modified | Size | Downloads / Week |
|---|---|---|---|
| Parent folder | |||
| Quartz.NET-3.21.0.zip | 2026-09-14 | 51.5 MB | |
| README.md | 2026-09-09 | 3.6 kB | |
| v3.21.0 source code.tar.gz | 2026-09-09 | 5.5 MB | |
| v3.21.0 source code.zip | 2026-09-09 | 6.2 MB | |
| Totals: 4 Items | 63.3 MB | 0 | |
Quartz.NET 3.21.0 carries the three fixes held back from 3.20.1 because each needed a small addition to the public surface or changed what a running scheduler does. All three were found while 4.0 was being finished; each is as old as 3.x. The public API grows by two interfaces on one class and nothing else; the schema is 3.20's. Three of the changes alter behaviour, each marked Behavior change worth noting below.
:::shell
dotnet add package Quartz --version 3.21.0
What changed
ResumeAllclears every paused trigger group, not only the ones with triggers — the persistent store resumed the groups it found inQRTZ_TRIGGERSand then deleted only its all-groups marker, so a group paused while it held no triggers kept itsQRTZ_PAUSED_TRIGGER_GRPSrow and went on pausing whatever was scheduled into it afterwards. Pausing a group before anything is scheduled into it is a documented use of the exact-name matcher, so this was a row the store wrote on purpose and could not take back. The trailing delete now takes every group, asRAMJobStorehas always done. (#3721, [#3742], port of f76b04a468)- Behavior change worth noting: a group paused while empty no longer survives
ResumeAll. - A job store closes its lock handler when it shuts down —
RedisSemaphoreopened aConnectionMultiplexeron the first lock and kept it, with its heartbeat, for the life of the process, because nothing on the store's shutdown path reached the lock handler andISemaphorehad no member that meant "we are done". On a branch that targetsnetstandard2.0andnet462an interface cannot gain a default member, soJobStoreSupport.Shutdownnow disposes a lock handler that implementsIAsyncDisposableorIDisposable, after the misfire handler, the cluster manager and the connection manager have stopped, logging and continuing if that throws;RedisSemaphoreimplements both and closes the multiplexer it opened. (#3721, [#3742], port of [#3639]) - Behavior change worth noting: a custom
ISemaphorethat implements either interface is now disposed at shutdown. - A configured wait longer than the platform's timer ceiling is refused where it is set —
Task.Delayrefuses anything longer than about 49.7 days on .NET and about 24.9 days on .NET Framework, with anArgumentOutOfRangeExceptionnaming a parameter calleddelay, and every duration Quartz waits out that way was accepted unchecked and reported later from wherever the wait happened.MisfireHandlerFrequency,MisfireThreshold(when it is also the handler's sleep),ClusterCheckinInterval,DbRetryInterval,TransientRetryInterval, the row-lock handlers'RetryPeriod,StartDelayed's argument andQuartzHostedServiceOptions.StartDelaynow name the setting, the ceiling and the value at configuration time. The ceiling is per target framework, held to whatTask.Delayactually accepts by a test. (#3721, [#3742], port of [#3577]) - Behavior change worth noting: a value past the ceiling now fails at configuration rather than later.
Public API — additive only
Quartz.Extensions.Redis:RedisSemaphoreimplementsIAsyncDisposableandIDisposable.
Upgrading
dotnet add package Quartz --version 3.21.0. Nothing to migrate. The 4.0 line is the current major; the 4.x migration guide is the way there, and 4.0.1 made the upgrade one a dependency bot can offer.
Full changelog: https://github.com/quartznet/quartznet/compare/v3.20.1...v3.21.0