Add Spring.Scheduling.Quartz4 for Quartz.NET 4.x alongside Spring.Scheduling.Quartz3

Aperta
#388 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
25/100
Tipo di issue
Funzionalità
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
csharp
Ambito
backend, databases

Direzione di ricerca

Start with the Quartz 4 migration guide linked in the issue and inspect src/Spring/Spring.Scheduling.Quartz3 alongside the project, build, and test configuration named in the work items. The issue identifies the required package, compatibility changes, and test areas, but leaves transaction design, source sharing, and configuration choices open. Done means a net10.0 Quartz 4 package, working transaction and scheduler integration, tests, example, documentation, and build support.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

New Feature

Summary

Add a Spring.Scheduling.Quartz4 package for Quartz.NET 4.x, shipped alongside the existing Spring.Scheduling.Quartz3. Quartz 4 isn't a drop-in upgrade for the current integration. It changes the job and job-factory contracts. It also removes StdSchedulerFactory and the process-wide singletons that SchedulerFactoryObject is built on, and it no longer supports subclassing the ADO.NET job stores, which LocalDataSourceJobStore relies on. So it needs its own package. Spring.Scheduling.Quartz3 stays for 3.x users, and Quartz 3.x is still maintained.

Quartz.NET 4.x facts

  • Releases. 4.0.0 through 4.7.1 are on nuget.org; 4.7.1 is the latest. 3.x is still maintained: 3.22.9 shipped on 2026-10-26, and recent 3.x patches come out alongside 4.x releases.
  • Target framework. Quartz 4.7.1 ships only net10.0: no netstandard2.0 and no .NET Framework. 3.22.9 ships net462, net472, netstandard2.0, net8.0, net9.0 and net10.0.
  • Dependencies. 4.x depends on Microsoft.Extensions.* 10.0.0: DependencyInjection, Hosting.Abstractions, Logging.Abstractions, Options.ConfigurationExtensions, Configuration.Binder and Diagnostics.HealthChecks. That's fine for a net10.0-only package. Spring's own floors stay at 8.0.x.
  • Merged packages. Quartz.Extensions.DependencyInjection, Quartz.Extensions.Hosting and Quartz.Serialization.SystemTextJson are now part of Quartz. One assembly can't reference Quartz 3 and Quartz 4 at once.
  • Migration guide. All of the points above come from it: docs/documentation/quartz-4.x/migration-guide.md @ v4.7.1.

What changes for the Spring integration

The code is in src/Spring/Spring.Scheduling.Quartz3, namespace Spring.Scheduling.Quartz. Each type is marked A (compiles unchanged), B (mechanical change) or C (design change).

Spring type Quartz 4 change Class
SchedulerFactoryObject StdSchedulerFactory and its 47 constants are gone. The replacement is QuartzSchedulerBuilder.UseProperties(...) / BuildScheduler(). Flat quartz.* keys still work, but a key that names a component by type is refused unless QuartzLegacyComponentKeysSupport is on. SchedulerRepository.Instance and DBConnectionManager.Instance are gone, replaced by an ISchedulerRepository and an IDbProvider resolved from the container. Today Spring uses these for the "already registered" check and for ExposeSchedulerInRepository, and it hands the [ThreadStatic] ConfigTimeDbProvider over at config time. The SchedulerFactoryType property ("any ISchedulerFactory") no longer maps to anything. C
LocalDataSourceJobStore (derives from JobStoreCMT) and SpringDbProviderAdapter JobStoreCMT is now ExternalTransactionJobStore, and subclassing the ADO.NET stores to change transaction handling is unsupported. The guide says "implement IJobStore" for that. The overrides that join Spring-managed transactions through ConnectionUtils (GetNonManagedTXConnection and CloseConnection) have no 4.x hook. This is the hardest item. C
AdaptableJobFactory, SpringObjectJobFactory IJobFactory.NewJob(...) / ReturnJob(IJob) becomes ValueTask<JobScope> CreateJob(bundle, scheduler, ct) / ReturnJob(JobScope, ct). C
LocalTaskExecutorThreadPool IThreadPool now runs ValueTask delegates and takes a CancellationToken. It's registered with UseThreadPool(...). B/C
QuartzJobObject, DelegatingJob, MethodInvokingJob, StatefulMethodInvokingJob Task Execute(IJobExecutionContext) becomes ValueTask Execute(IJobExecutionContext, CancellationToken). QuartzJobObject.ExecuteInternal is the extension point users override, so its signature changes are source-breaking for subclasses. B
CronTriggerObject, SimpleTriggerObject The misfire instruction int constants become per-trigger enums (CronTriggerMisfireInstruction and others). Spring maps MisfireInstructionName through reflection over the old constants, so that mapping has to be rewritten. There are also behaviour changes, such as cron day-field and DST semantics and an inclusive EndTime for simple triggers; document them, don't paper over them. B
JobDetailObject, MethodInvokingJobDetailFactoryObject They use JobDetailImpl and JobKey, which are still there. Check that the setters Spring uses survive. B (to verify)
SchedulerAccessor, SchedulerAccessorObject Calls move to the ValueTask / CancellationToken overloads. Check the XMLSchedulingDataProcessor usage against 4.x. B (to verify)
ITaskExecutor, IThreadRunnable, MethodInvokingRunnable, SchedulingException, TaskRejectedException, IJobDetailAwareTrigger, ISchedulerContextAware Spring-owned types with no Quartz 4 impact, apart from ISchedulerContextAware, which is still there. A

Logging and serialization don't affect Spring's code. Quartz 4 logs through Microsoft.Extensions.Logging, and Spring doesn't wire Quartz's logging. Spring's Quartz types aren't [Serializable]. Users still have to follow Quartz's data migration: the 3.x→4.x schema script is mandatory, and 4.x can't read BinaryFormatter-serialized job data. The package README should link to that, not repeat it.

Proposal

  • Package and assembly: Spring.Scheduling.Quartz4, targeting net10.0 only ($(TargetModernFrameworkVersion)). No other target is possible.
  • Namespace: keep Spring.Scheduling.Quartz. The Quartz 2→3 move set the precedent: users switching packages change the assembly name in assembly-qualified XML type="..." references, and C# code that doesn't subclass the job contracts keeps compiling.
  • Sources:
    • The A and B types are compiled from Spring.Scheduling.Quartz3 by link, with a QUARTZ4 define for the signature differences (ValueTask and cancellation tokens).
    • SchedulerFactoryObject, the job-store bridge, the job factory and the thread pool get Quartz4-only files, because they differ too much for #if.
    • The alternative is a full copy. That's simpler to reason about, but it doubles maintenance of the shared types.
  • Central package management: Directory.Packages.props keeps Quartz at 3.22.9. The Quartz4 projects use <PackageReference Include="Quartz" VersionOverride="4.x" />. Check how Dependabot handles VersionOverride, and add a dependabot.yml rule so that a Quartz 4 bump is never proposed for the Quartz 3 projects.
  • Transactions: redesign Spring transaction participation for 4.x. Options, in order of preference:
    1. Supply Spring's provider with UsePersistentStore(s => s.UseConnectionProvider(...)) and UseAmbientTransactions() (the ExternalTransactionJobStore path), using a connection provider that hands out Spring's transaction-bound connection. Check how the store releases connections.
    2. A custom IJobStore built on DelegatingJobStore.
    3. Drop job-store transaction participation for 4.x and document it.
  • Configuration: move SchedulerFactoryObject to QuartzSchedulerBuilder. Keep QuartzProperties (flat keys), JobFactory, DbProvider, TaskExecutor, Triggers/JobDetails, AutoStartup/StartupDelay and WaitForJobsToCompleteOnShutdown, so XML configurations port with minimal edits. Drop SchedulerFactoryType in 4.x, unless there is a builder-level equivalent.

Work items

  • src/Spring/Spring.Scheduling.Quartz4 project (net10.0, VersionOverride, metadata, tags), added to Spring.Net.sln
  • Linked shared sources plus the QUARTZ4 signature differences
  • New SchedulerFactoryObject on QuartzSchedulerBuilder, with repository/exposure semantics on ISchedulerRepository
  • Job-store / Spring transaction bridge (see the options above)
  • IJobFactory port (JobScope) and the IThreadPool adapter
  • Misfire-instruction mapping onto the 4.x enums
  • test/Spring/Spring.Scheduling.Quartz4.Tests (net10.0), linking the shared Quartz3 tests, with 4.x-specific factory and job-store tests; integration tests against SQL Server with the 4.x schema
  • Example: a Quartz 4 variant of examples/Spring/Spring.Scheduling.Quartz.Example
  • README.md for the package, including links to Quartz's 3→4 migration guide and the schema script
  • Package validation: there is no 3.1.0 baseline for a new package, so turn EnablePackageValidation off for it until 4.0.0 ships
  • build-support/build: add it to the packed modules in Build.cs, and confirm the test selection
  • BreakingChanges.txt / docs: the 3→4 differences, including ExecuteInternal's signature and the behaviour changes above
  • .github/dependabot.yml: rules for Quartz 3 vs 4

Open questions

  1. Ship in 4.0.0, or in a 4.x minor after 4.0?
  2. Linked sources with a QUARTZ4 define, or a full copy?
  3. How should the job store take part in Spring transactions on 4.x (options 1–3 above)?
  4. Should SchedulerFactoryObject stay property-bag compatible (QuartzProperties), or move to typed options as well?
  5. Should the README point users who don't need Spring-managed triggers or jobs to Quartz 4's native AddQuartz(...) hosting?
  6. Should Spring.Scheduling.Quartz3 be marked as maintenance-only once this ships?

Related: #297 / #298 (the earlier break in Quartz 3.12, from the SchedulerRepository change).

🤖 Generated with Claude Code

Lingua principale
C#
Stelle
883
Fork
374
Merge medio
2h 48m
PR unite (30g)
17

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di spring-projects/spring-net

Tutte le issue di spring-projects/spring-net

Issue simili

Altre issue su C#

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.