Download Latest Version Quartz.NET-4.5.1.zip (52.0 MB) Google Add to Preferred Sources
Home / v4.5.0
Name Modified Size InfoDownloads / Week
Parent folder
Quartz.NET-4.5.0.zip 2026-10-13 51.9 MB
README.md 2026-10-13 11.1 kB
v4.5.0 source code.tar.gz 2026-10-13 8.9 MB
v4.5.0 source code.zip 2026-10-13 11.2 MB
Totals: 4 Items   72.1 MB 0

Quartz.NET 4.5 is one dashboard for a fleet. It fronts schedulers in other processes, on other machines and in other clusters, and tells apart workers that all run QuartzScheduler. Targets fronting one clustered store show as one row with its nodes. A new package, Quartz.Dashboard.Agent, lets a worker dial out to the dashboard, so the worker opens no inbound port. Six more packages are proven under native AOT on every pull request. An application on 4.4 compiles on 4.5 unchanged, and the database schema did not change.

:::shell
dotnet add package Quartz --version 4.5.0

Highlights

  • A fleet, keyed target/name. Each AddQuartzHttpClient registration names its process with HttpClientOptions.Target, so w1/QuartzScheduler and w2/QuartzScheduler are two rows, beside store-attached windows and the local schedulers. Fleet
  • A cluster shows once. Targets that front one clustered store are detected and merged into one row, w1+w2+w3/QuartzScheduler, whose Cluster page starts, stands by, shuts down and interrupts each node. Fleet
  • Workers dial out: Quartz.Dashboard.Agent. UseDashboardAgent connects a scheduler to a dashboard over SignalR. The dashboard enables it with AcceptAgents. The worker needs no inbound port, no HTTP API and no web framework. Dashboard agent
  • Secure by default. The agent refuses every job type a dashboard names until IsJobTypeAllowed is set. The hub reads its token from the Authorization header only. A hub with neither tokens nor a policy fails at startup. Dashboard agent
  • Native AOT, proven per package. Quartz.Jobs, Quartz.Plugins, Quartz.Plugins.TimeZoneConverter, Quartz.HttpClient, Quartz.AspNetCore and Quartz.Dashboard.Agent now say IsAotCompatible. Each one is published as a native executable and run on Windows, Linux and macOS on every pull request. Trimming and native AOT

Fleet

  • Identity is target/name (#4042, closes [#3774]).
  • The new public SchedulerRef(SchedulerName, Target) is the key a dashboard addresses a scheduler by. Parse splits at the first /. A bare name is the key of a scheduler reached through no target.
  • HttpClientOptions.Target names the process. It becomes the client's service key and the first half of the key. / and + are refused.
  • The Schedulers page shows one row per key, with Target and Reached columns. The picker groups by target, and remembers the selection in the qz_scheduler cookie.
  • The HTTP API's {name} resolves to the untargeted entry only. A name held only by targets answers 404, naming the targets.
  • A local scheduler whose own name contains / keeps that name everywhere: in resolution, authorization, history and live logs.
  • A cluster behind several targets is one row (#4042).
  • A fleet monitor asks every target which nodes it sees at QuartzDashboardOptions.ClusterDetectionInterval, one minute by default. Targets on one clustered store merge into a+b+c/name.
  • Membership is sticky: a node that stops answering stays in its cluster as unreachable, so the key changes on a topology change, never on an outage. Each round elects a preferred member from the targets that answered.
  • The Cluster page reaches each node through its member key. A cluster-wide lifecycle verb is refused, because a cluster has no single lifecycle.
  • Log events 9105–9110.
  • SchedulerRegistration gains Key, Members and LastSeenUtc. GET …/schedulers rows gain members and lastSeenUtc. SchedulerResource.Target lets an authorization policy see which process it is asked about.

Dashboard agent

  • New package Quartz.Dashboard.Agent (#4044, closes [#3773]).
  • Worker: UseDashboardAgent(o => { o.Endpoint = new("https://ops.example/quartz/agents"); o.Token = …; o.Target = "w1"; }).
  • Dashboard: AcceptAgents(a => a.Tokens.Primary = …).
  • The connection retries forever, from 1 s back to 30 s. The dashboard shows the worker Unknown, with when it was last seen, after three missed heartbeats (45 s by default). It forgets the worker after ForgetAfter, one hour by default. A restarted worker comes back on the same row.
  • History, live logs and every page work over the connection. History is read through the tunnel and the database schema is unchanged.
  • Only the SignalR client is referenced, with no Microsoft.AspNetCore.App.
  • What the agent accepts is decided on the worker.
  • ReadOnly, IsOperationAllowed, MaxConcurrentOperations (a bounded queue; overflow answers 503), MaxPageSize, and a message cap of 4 MiB by default.
  • IsJobTypeAllowed unset refuses every request that stores a job by type name, with 403. Triggering, pausing, rescheduling and deleting existing jobs all work.
  • A cancelled or timed-out operation is cancelled on the worker too, whether it is queued or running.
  • How the hub is authorized.
  • Bearer tokens in two slots, Primary and Secondary, for rotation. They are compared in constant time and read from the Authorization header only, never from a query string, because a URL ends up in access logs.
  • Alternatively, an AuthorizationPolicy.
  • A token-only hub stays reachable under a fail-closed fallback policy.
  • Log events 9111–9117 (dashboard) and 9300–9305 (agent).
  • One dashboard instance per deployment in agent mode: the agent registry lives in the process.

Trimming and native AOT

  • Six side packages say IsAotCompatible (#4051, part of [#3341]).
  • Quartz.Trimming.Canary runs Quartz.Jobs, Quartz.Plugins and Quartz.Plugins.TimeZoneConverter as a native executable.
  • Quartz.Trimming.Canary.Wire runs Quartz.AspNetCore, Quartz.HttpClient and Quartz.Dashboard.Agent the same way.
  • The build fails on any warning a package's baseline does not record. None of the six produces an IL3050.
  • VerifyReferenceAotCompatibility stops listing them.
  • Quartz.Jobs records no trim warning any more.
  • Quartz.Extensions.Redis, Quartz.Aspire and the Quartz.Weasel* packages stay trimmable without the claim, because each needs a server or a database that nothing can run natively here. Which packages say whether they can be trimmed

Scheduling and the dashboard

  • A freed execution-limit slot wakes the scheduler loop (#4041, closes [#4033]). A node parked until its next look used to wait out that look when a firing ended in a group held at its limit, or when a held pinned trigger became free. Now:
  • it looks again as soon as the slot frees;
  • while a held trigger is re-polled early, the look-ahead is bounded so the node acquires nothing that is due after its next look.
  • The Backfill dialog's preview says when Max slots would refuse the range, and how far the spacing spreads it (#4038, closes [#4037]). Thanks to @dongfo, in a first contribution.

Behaviour changes

Before After What to do
IQuartzApiClient members took a bare scheduler name They take a key; a bare name is the key of a scheduler reached through no target Nothing for a 4.4 deployment. A replacement client parses keys with SchedulerRef.Parse
The HTTP API's {name} resolved to the first entry under the name It resolves to the untargeted entry only Nothing for a 4.4 deployment
AddQuartzHttpClient was keyed by the scheduler name It is keyed by Target when one is set If you set Target, resolve GetRequiredKeyedService<IScheduler>(target)
A second Target of the same name was impossible It throws SchedulerConfigException Give each process a Target of its own
AddQuartzDashboard() registered no scheduler repository It registers Quartz's shared services, so an agent-only dashboard needs no AddQuartz Nothing
The Schedulers page showed one row per name It shows one row per key, and one row per detected cluster Nothing

Upgrading

An application on 4.4 compiles on 4.5 unchanged. No migration to run: the schema is the same, and 4.4 and 4.5 nodes run side by side on one store. Every addition and behaviour change is in the migration guide's Upgrading from 4.4 to 4.5.

Public API

Additions only: +66 lines, none removed, and no interface gained a member.

Assembly Lines added
Quartz.Dashboard 24
Quartz.Dashboard.Agent (new) 23
Quartz 15
Quartz.HttpClient 3
Quartz.AspNetCore 1

Quartz.Dashboard now depends on Quartz.HttpClient, at the same version. The whole delta, member by member: git diff v4.4.0 v4.5.0 -- src/Quartz.Tests.Unit/Verify src/Quartz.Tests.AspNetCore/Verify.

Also

  • The docs build takes patched npm dependencies (#4040). Test, analyzer and Aspire hosting packages were updated.
  • The comparison page describes 4.5 (#4050).
  • Marten and Wolverine are held at 9.45 and 6.45 in the tests and examples while the Weasel floor holds at 9.39.0 (#4056).

What's Changed

Other changes

New Contributors

Full Changelog: https://github.com/quartznet/quartznet/compare/v4.4.0...v4.5.0

Source: README.md, updated 2026-10-13