Repository navigation
Update dependency Quartz.AspNetCore to v4 - #1869
Open
renovate[bot] wants to merge 1 commit into
Open
renovate[bot] wants to merge 1 commit into
renovate[bot] wants to merge 1 commit into
Conversation
renovate
Bot
force-pushed
the
renovate/major-quartznet-monorepo
branch
2 times, most recently
from
September 13, 2026 13:22
a40a671 to
db92354
Compare
renovate
Bot
force-pushed
the
renovate/major-quartznet-monorepo
branch
2 times, most recently
from
September 25, 2026 16:49
a094daa to
f5ecc47
Compare
renovate
Bot
force-pushed
the
renovate/major-quartznet-monorepo
branch
4 times, most recently
from
September 29, 2026 15:53
e5676e1 to
768cbf4
Compare
renovate
Bot
force-pushed
the
renovate/major-quartznet-monorepo
branch
2 times, most recently
from
October 13, 2026 21:49
6458b83 to
d3e99b2
Compare
renovate
Bot
force-pushed
the
renovate/major-quartznet-monorepo
branch
from
October 15, 2026 16:46
d3e99b2 to
9279bbe
Compare
renovate
Bot
force-pushed
the
renovate/major-quartznet-monorepo
branch
from
October 20, 2026 14:07
9279bbe to
8d21d43
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note
This PR body was truncated due to platform limits.
This PR contains the following updates:
3.15.1→4.6.0Release Notes
quartznet/quartznet (Quartz.AspNetCore)
v4.6.0Quartz.NET 4.6 is about clusters under load. A firing round of work that allows concurrent execution takes no
TRIGGER_ACCESSlock, and a round reads each concern once whatever its size. An interrupt reaches the node running the firing, through the store. A node can serve only the execution groups it is configured for, and execution history can write behind. A trimmed or native publish now records no Quartz trim warning, and eight packages are proven under native AOT. An application on 4.5 compiles on 4.6 unchanged, unless it treats warnings as errors and has a cron literal that the new analyzer warningQZ0007reports. The upgrade has three required database migrations, each one nullable column that can run while 4.5 nodes are up; see Upgrading from 4.5 to 4.6.Highlights
TRIGGER_ACCESS. It is on by default, with an off switch. While any 4.5 node is live, every round takes the lock as before. SQL Server keeps the lock. ClusteringInterruptandInterruptFireInstancerecord a request for a firing on another node, and that node cancels the job's token after its next check-in.CancelPreviousnow works across nodes too. ClusteringExecutionHistoryOptions.WriteBehindIntervalset, a completion is queued and flushed with one status update per job per flush, at close to history-off throughput. Execution historyWithMisfireThresholdlets one trigger tolerate a longer delay, or a shorter one, without moving the store's threshold for every other trigger.DefaultMisfireHandlingsets what an unstated misfire instruction becomes, for every trigger type. TriggersPublishTrimmedandPublishAot.Quartz.Weasel.SQLitejoins the packages proven native on every pull request. Trimming and native AOTClustering
AdoJobStoreOptions.LockFreeFiringRounds, defaulttrue; flat keyquartz.jobStore.lockFreeFiringRounds.falserestores 4.5's rounds.QRTZ_SCHEDULER_STATE.QUARTZ_VERSION, from the required migration4.6/add_scheduler_version. While any 4.5 node is live, every round takes the lock (event 3517); once the last one ages out, rounds go lock-free (event 3518).[DisallowConcurrentExecution]candidate, takes it.contention, event 3060) until the backlog clears or 2 s pass, so a drained backlog is no slower than under 4.5.INTERRUPT_REQUESTED_TIMEon the firing'sQRTZ_FIRED_TRIGGERSrow, from migration4.6/add_fired_trigger_interrupt. The node running the firing reads its requests after every check-in, so a request lands within oneCheckinInterval, 7.5 seconds by default.truefromInterruptmeans interrupted here or asked, not stopped.CancelPreviousasks a 4.6 peer instead of waiting asBufferOne. The two firings overlap for up to one check-in interval.UseClustering()used to leave every node atNON_CLUSTERED.Execution groups
IConfigurationkeep their case, and an execution-limit prefix such astenant:*can be configured (#4107, closes #4093).Execution history
ExecutionHistoryOptions.WriteBehindIntervalqueues each completion; one writer per store flushes every interval, or at 256 waiting runs, in one transaction with oneQRTZ_JOB_STATUSupdate per job. In the census, history on ran at 276 firings per second, write-behind at 379, and history off at 388.4.6/add_execution_history_lookup_indexes.Triggers
TriggerBuilder<TJob>.WithMisfireThreshold(TimeSpan),ITrigger.MisfireThreshold: positive, whole milliseconds;nullis the store'sMisfireThreshold, as before.[CronTrigger]/[SimpleTrigger]MisfireThreshold(checked by the new analyzer errorQZ0008), the JSON and XML schedules,TriggerDetailsUpdate, the HTTP API'supdate-detailsand the dashboard's Edit details.NEXT_FIRE_TIME.QRTZ_TRIGGERS.MISFIRE_THRESHOLD, from the required migration4.6/add_trigger_misfire_threshold. A 4.5 node applies the store's threshold, so a cluster honours per-trigger thresholds once every node is 4.6.QuartzSchedulerOptions.DefaultMisfireHandling(SmartPolicy,IgnoreMisfires,FireAndProceed,DoNothing; flat keyquartz.scheduler.defaultMisfireHandling) is mapped to each trigger type's own instruction when a trigger whose instruction was never stated is stored. An explicitWithMisfireHandlingInstructionSmartPolicy()stays smart policy. The storedMISFIRE_INSTRis always explicit, so a 4.5 node reads the same number.Configuration and diagnostics
ConfigureAllQuartzSchedulerschooses afterAddQuartzreplaces the default, soAddQuartzPersistentStoreworks in either order (#4121, closes #4104). Thanks @tzdevelopteam for the repro.QZ0007flags a*seconds field under a restricted minute or hour, such as* */5 * ? * *(#4115, closes #4096). Thanks @ybai08, whose parallel work in #4111 reached the same rule.JobExecutionContextBuildersets recovery, retry, refire, calendar and cancellation, andJobRunTimeuses theTimeProvider(#4119, closes #4097).Trimming and native AOT
Quartz.TypeNameResolution.IsSupportedandQuartz.LegacyComponentKeys.IsSupported.TypeConverter(#4089, closes #4082; #4129). Feature switchQuartz.JobData.IsTypeConverterCoercionSupported(MSBuildQuartzJobDataTypeConverterSupport).DateOnly,TimeOnly,Half,Int128andUInt128convert on the switch-free path. The trim baseline goes to zero.Quartz.Weasel.SQLitesaysIsAotCompatible(#4129), and the canary proves aDbDataSourcestore natively. Eight packages are now proven.Documentation
Thanks
QZ0007work in #4111, and for the report that tests failed outside UTC (#4124).AddQuartzPersistentStoreordering repro (#4104).What's Changed
Documentation
Other changes
Full Changelog: quartznet/quartznet@v4.5.1...v4.6.0
v4.5.1Three packages take the fixed versions of dependencies named in Microsoft's October 13 security advisories. There is no public API change and no schema change, and no other package changes.
Fixed
Quartz.Dashboard.AgentrequiresMicrosoft.AspNetCore.SignalR.Client10.0.13. 4.5.0 required 10.0.0, and every SignalR client before 10.0.13 brings aMicrosoft.AspNetCore.SignalR.Commoncovered by GHSA-334f-vvp4-7g6p (CVE-2026-70159). So an application referencing the agent got NU1903 at restore, and that is an error wherever warnings are errors. The fixed client asks forMicrosoft.Extensions.DependencyInjection,LoggingandLogging.Abstractions10.0.13 or later, so an application referencing the agent now resolves those at least that high. The agent's own nuspec no longer repeats the framework-extension floors it inherits fromQuartz. (#4065)Quartz.Weasel.OracleandQuartz.Weasel.SqlServerrequireSystem.Security.Cryptography.Pkcs9.0.21. Their database drivers, reached through Weasel, bring Pkcs 8.0.0 and 9.0.4, which GHSA-2fmv-rv2c-59x7 and GHSA-846f-f764-76mx cover. Neither package calls it. The direct reference lifts an application's graph to the fixed version, and can go once the drivers require a fixed one themselves. (#4065)The same SignalR fix ships for 3.x's
Quartz.Dashboardin 3.22.6.What's Changed
Other changes
Full Changelog: quartznet/quartznet@v4.5.0...v4.5.1
v4.5.0Quartz.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.Highlights
target/name. EachAddQuartzHttpClientregistration names its process withHttpClientOptions.Target, sow1/QuartzSchedulerandw2/QuartzSchedulerare two rows, beside store-attached windows and the local schedulers. Fleetw1+w2+w3/QuartzScheduler, whose Cluster page starts, stands by, shuts down and interrupts each node. FleetQuartz.Dashboard.Agent.UseDashboardAgentconnects a scheduler to a dashboard over SignalR. The dashboard enables it withAcceptAgents. The worker needs no inbound port, no HTTP API and no web framework. Dashboard agentIsJobTypeAllowedis set. The hub reads its token from theAuthorizationheader only. A hub with neither tokens nor a policy fails at startup. Dashboard agentQuartz.Jobs,Quartz.Plugins,Quartz.Plugins.TimeZoneConverter,Quartz.HttpClient,Quartz.AspNetCoreandQuartz.Dashboard.Agentnow sayIsAotCompatible. Each one is published as a native executable and run on Windows, Linux and macOS on every pull request. Trimming and native AOTFleet
target/name(#4042, closes #3774).SchedulerRef(SchedulerName, Target)is the key a dashboard addresses a scheduler by.Parsesplits at the first/. A bare name is the key of a scheduler reached through no target.HttpClientOptions.Targetnames the process. It becomes the client's service key and the first half of the key./and+are refused.qz_schedulercookie.{name}resolves to the untargeted entry only. A name held only by targets answers404, naming the targets./keeps that name everywhere: in resolution, authorization, history and live logs.QuartzDashboardOptions.ClusterDetectionInterval, one minute by default. Targets on one clustered store merge intoa+b+c/name.9105–9110.SchedulerRegistrationgainsKey,MembersandLastSeenUtc.GET …/schedulersrows gainmembersandlastSeenUtc.SchedulerResource.Targetlets an authorization policy see which process it is asked about.Dashboard agent
Quartz.Dashboard.Agent(#4044, closes #3773).UseDashboardAgent(o => { o.Endpoint = new("https://ops.example/quartz/agents"); o.Token = …; o.Target = "w1"; }).AcceptAgents(a => a.Tokens.Primary = …).ForgetAfter, one hour by default. A restarted worker comes back on the same row.Microsoft.AspNetCore.App.ReadOnly,IsOperationAllowed,MaxConcurrentOperations(a bounded queue; overflow answers503),MaxPageSize, and a message cap of 4 MiB by default.IsJobTypeAllowedunset refuses every request that stores a job by type name, with403. Triggering, pausing, rescheduling and deleting existing jobs all work.PrimaryandSecondary, for rotation. They are compared in constant time and read from theAuthorizationheader only, never from a query string, because a URL ends up in access logs.AuthorizationPolicy.9111–9117(dashboard) and9300–9305(agent).Trimming and native AOT
IsAotCompatible(#4051, part of #3341).Quartz.Trimming.CanaryrunsQuartz.Jobs,Quartz.PluginsandQuartz.Plugins.TimeZoneConverteras a native executable.Quartz.Trimming.Canary.WirerunsQuartz.AspNetCore,Quartz.HttpClientandQuartz.Dashboard.Agentthe same way.IL3050.VerifyReferenceAotCompatibilitystops listing them.Quartz.Jobsrecords no trim warning any more.Quartz.Extensions.Redis,Quartz.Aspireand theQuartz.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 trimmedScheduling and the dashboard
Behaviour changes
IQuartzApiClientmembers took a bare scheduler nameSchedulerRef.Parse{name}resolved to the first entry under the nameAddQuartzHttpClientwas keyed by the scheduler nameTargetwhen one is setTarget, resolveGetRequiredKeyedService<IScheduler>(target)Targetof the same name was impossibleSchedulerConfigExceptionTargetof its ownAddQuartzDashboard()registered no scheduler repositoryAddQuartzUpgrading
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.
Quartz.Dashboardnow depends onQuartz.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
What's Changed
Other changes
New Contributors
Full Changelog: quartznet/quartznet@v4.4.0...v4.5.0
v4.4.0Quartz.NET 4.4 is history you can run a business on. Each run says what it achieved: succeeded, failed,
cancelled or skipped, with a summary and metrics. The history keeps that per job, sweeps it by result and charts
it over time, and a health check degrades when a required job stops succeeding. Recovery respects rolling
deploys, and triggers already due fire in the transaction that acquires them: at 20 triggers a second on
PostgreSQL, 95–99 % of firings land within ±50 ms, up from 54 % on 4.3.0. Quartz.Weasel now manages the job store's schema on six databases, adding MySQL, Oracle and Firebird.
Highlights
context.Result, a status per job, retentionby result, and a chart of runs over time. Execution history and outcomes
RequireSuccessWithin(jobKey, TimeSpan.FromHours(26))degrades when a nightly jobstops succeeding. Execution history and outcomes
RunAtStartup, scheduling a triggeralready paused, and pausing a set of keys with a reason in one call. Scheduling
420–429 firings a second. Reliability and clustering
or the restarted node. Reliability and clustering
Quartz.Weasel.MySQL,Quartz.Weasel.OracleandQuartz.Weasel.FirebirdjoinPostgreSQL, SQL Server and SQLite. Databases and Weasel
HTTP API and dashboard
Execution history and outcomes
context.Result = JobRunReport.Skipped("…").With("released", 3).JobRunResult {Succeeded, Failed, Cancelled, Skipped}.1059/1060).
MisfireReason.Vetoed). Manual runs (TriggerJob) are marked.JobRunStatus: last run, last success and failure, consecutive failures, counts.RetentionByResult,MisfireRetention) andMaxEntriesPerJob.sweeps per cluster.
with history on went from 113–248 to 77–189 firings a second. Tracked in #3979.
database/migrations/database/migrations/…. (#3972)and the HTTP API's
JobExecutedevent carry it, not the wrapper's "Job threw an unhandled exception". Logtemplates are unchanged.
o.RequireSuccessWithin(new JobKey("nightly-report"), TimeSpan.FromHours(26)), or aRequiredJobslistbound from configuration.
IExecutionHistoryStore.QueryExecutionStatistics(a default member), with an HTTP route and a clientmember.
native
PERCENTILE_CONTon PostgreSQL and Oracle, a ranked read elsewhere.cards count the window rather than the page.
ExecutionHistoryOptions.RecordInputrecords a run'sJobInput, up toMaxInputBytes(default16 KB). Over the cap the input is not kept, and the row is flagged.
TriggerJob(key, data)and says whether it did.JOB_INPUTandJOB_INPUT_TOO_LARGE, in the optional 4.4 migration.quartz.job.execution.durationgains aquartz.job.resulttag:succeeded,failed,cancelledorskipped, classified by the same rule as the history row.error.typeis unchanged: it is set on a failedrun that threw. (#4004, closes #3967)
Quartz.Job.Executespan getsquartz.job.resulttoo. A failed store span now carrieserror.type.(#4020, closes #4016)
QuartzSchedulerOptions.RecordExceptionSpanEvents, since OpenTelemetry deprecated span events in 2026.Unset, Quartz follows
OTEL_SEMCONV_EXCEPTION_SIGNAL_OPT_IN, sologsturns the events off. The default isunchanged. (#4020)
Scheduling
[RetryPolicy(3, "00:00:30")](Fixed),[RetryPolicy(5, "00:00:10", 2.0)](Exponential), Explicit delays,or
[RetryPolicy(0)](never), plusq.UseDefaultRetryPolicy(…).RetryPolicy.Nonerefuses at any level.event 1062).
SendMailJobandNativeJobcarry[RetryPolicy(0)].q.RunAtStartup(jobKey).twice gives one run.
@rebootis still rejected, and its message namesRunAtStartup.ScheduleJobOptions/AddTriggerOptionsgainPaused,PauseReasonandPauseRequestedBy. The shippedstores write the trigger paused in the same write, so it never fires first.
IJobStore.SupportsStoringPauseddefault member. Without it, thescheduler pauses the trigger straight after storing it; the gap between the two is documented.
PauseTriggersWith/PauseJobsWithonIScheduler,IJobStoreandIQuartzApiClient./keys/pauseroutes take the reason. A reasonless 4.3 client still gets the exact reasonlesspause.
IJobListener.JobProgressChanged(context, progress), a default member.per firing, and only on a change.
JobWasExecuted. It is called off the job's thread and is in-processonly.
Reliability and clustering
The database store makes one transaction per round instead of two, and sends each round's claims and fire
writes as one batch each.
The in-memory store takes one lock per round instead of two.
PostgreSQL, against the released 4.3.0 (three alternating sittings; the full table is under Measured):
A custom
IJobStorekeeps the old two-step path through the newAcquireNextTriggersAndFireDuedefaultmember.
A custom
StdAdoDelegatekeeps every override it has. The newIDriverDelegate.SupportsFireOnAcquireanswers true only for the shipped delegates, and a subclass gets the one-transaction round through the
per-trigger members it may override.
closes #3988).
worst firing went from 12.9 s late to 0.37 s.
unchanged.
AdoJobStoreOptions.RecoverFiringsCancelledByShutdown(keyquartz.jobStore.recoverFiringsCancelledByShutdown).RequestsRecoveryjob cancelled by a graceful shutdown gets a recovery trigger instead of completing asCancelled. A peer, or the restarted node, runs it on its next acquisition.
Interruptor[JobTimeout]stays a cancellation. The in-memory store is not affected.in a row it is stored ERROR. Before, it was released and acquired again forever, which hot-looped and starved
its
[DisallowConcurrentExecution]job-mates.AdoJobStoreOptions.MaxConsecutiveFireFailures(default 5, 0 = never), flat keyquartz.jobStore.maxConsecutiveFireFailures.ResetTriggerFromErrorState.InMemoryJobStoreOptions.MaxConsecutiveFireFailuresfailures in a row (log events 2008/2009).
unexpectedly.
closes #3985 and #4006).
BLOCKED.being parked within milliseconds. They are counted only after the store's own commit, and a successful
misfire resets the count.
event 3053). New in-memory event 2010.
AddCalendar(…, updateTriggers: true)works out every trigger's new fire time on a clone first, and fails asthe database store does, with
JobPersistenceException.Databases and Weasel
UseWeaselForMySql()andUseWeaselForOracle().GET_LOCKuser lock,which needs no privilege.
CURRENT_SCHEMA. There is no lock, becauseDBMS_LOCKneeds a grant. Aconflicting apply re-reads and retries, as
ProvisionSchema()does.unchanged; 3.20, 4.2 and 4.3 databases upgrade add-only; an application's own objects survive.
UseWeaselForFirebird(), for Firebird 3, 4 and 5.9.39.0.
MaxIdentifierLengthallows up to 63 on Firebird 4 andlater.
[9.39.0, 10.0.0).IDX_QRTZ_T_NFT_STon every apply. JasperFx/weasel#660fixed it upstream, so Quartz.Weasel.Oracle needs no workaround.
code. Every failure surfaces as a
SchedulerExceptionwith the original inside.their rows. 4.3 refused. Thanks to the 11 upstream fixes in Weasel 9.36.0. (#3978, closes #3956)
columns, types, keys, foreign keys and teardown.
ProvisionSchema()leaves it out too, as the fresh-install script always has.Thanks to the JasperFx maintainers for reviewing and merging Weasel.Firebird (JasperFx/weasel#666).
Weasel schema management
Database schema
Configuration
📅 Schedule: (in timezone Asia/Shanghai)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.