EasyCore.Quartz 8.3.0

dotnet add package EasyCore.Quartz --version 8.3.0
                    
NuGet\Install-Package EasyCore.Quartz -Version 8.3.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EasyCore.Quartz" Version="8.3.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="EasyCore.Quartz" Version="8.3.0" />
                    
Directory.Packages.props
<PackageReference Include="EasyCore.Quartz" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add EasyCore.Quartz --version 8.3.0
                    
#r "nuget: EasyCore.Quartz, 8.3.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package EasyCore.Quartz@8.3.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=EasyCore.Quartz&version=8.3.0
                    
Install as a Cake Addin
#tool nuget:?package=EasyCore.Quartz&version=8.3.0
                    
Install as a Cake Tool

โฑ๏ธ EasyCore.Quartz

EasyCore.Quartz is a production-oriented job scheduling library for .NET 8. Built on Quartz.NET, it provides attribute-based jobs, an English ops dashboard, REST management APIs, dynamic HTTP jobs, and persistence with clustering for MySQL / SQL Server / PostgreSQL / Oracle.

.NET C# Quartz Dashboard DB License Version


๐ŸŒ Language


๐Ÿ“š Table of Contents

Part I โ€” Overview & Architecture

Part II โ€” Getting Started

Part III โ€” Dashboard ยท REST ยท HTTP Jobs

Part IV โ€” Persistence & Production


1. Positioning

EasyCore.Quartz makes Quartz easy, operable, and production-safe in ASP.NET Core:

Pain point EasyCore.Quartz approach
Manual job wiring IEasyCoreJob + [EasyCoreCron] auto-discovery
No ops UI Optional package EasyCore.Quartz.Dashboard (/easy-quartz)
Split management APIs Shared IJobManagementService (Dashboard + REST)
Multi-DB persistence Separate MySQL / SQL Server / PostgreSQL / Oracle packages
Swallowed exceptions JobWrapper logs and rethrows
Accidental public exposure Dashboard Basic Auth; username/password required

1.1 Design Principles

Principle Meaning
Low friction One extension method + one attribute to get running
Operable Full dashboard: Overview / Jobs / History / โ€ฆ
Pluggable storage Core and DB packages are separate
Failure-aware Exceptions propagate; History records outcomes
Secure by default Empty authorization list โ‡’ reject dashboard access

1.2 Repository Layout

EasyCore.Quartz/
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ EasyCore.Quartz/                 # Core: discovery, management, REST, History
โ”‚   โ”œโ”€โ”€ EasyCore.Quartz.Dashboard/       # English ops dashboard
โ”‚   โ”œโ”€โ”€ EasyCore.Quartz.MySql/
โ”‚   โ”œโ”€โ”€ EasyCore.Quartz.SqlServer/
โ”‚   โ”œโ”€โ”€ EasyCore.Quartz.PostgreSql/
โ”‚   โ””โ”€โ”€ EasyCore.Quartz.Oracle/
โ”œโ”€โ”€ demo/
โ”‚   โ”œโ”€โ”€ WebApp.Quartz.InMemory/          # :5101 โ€” each demo owns SampleJob
โ”‚   โ”œโ”€โ”€ WebApp.Quartz.MySql/             # :5102
โ”‚   โ”œโ”€โ”€ WebApp.Quartz.SqlServer/         # :5103
โ”‚   โ”œโ”€โ”€ WebApp.Quartz.PostgreSql/        # :5104
โ”‚   โ””โ”€โ”€ WebApp.Quartz.Oracle/            # :5105
โ”œโ”€โ”€ tests/EasyCore.Quartz.Tests/
โ””โ”€โ”€ docs/svg/

2. Architecture

2.1 Component Diagram

architecture-en

2.2 Job Lifecycle

sequence-en

2.3 Data Flow

[EasyCoreCron Job]
       โ”‚
       โ–ผ
 JobTypeDiscovery โ”€โ”€โ–บ JobWrapper<T> โ”€โ”€โ–บ Quartz Scheduler
       โ”‚                                      โ”‚
       โ”‚                                      โ–ผ
       โ”‚                            JobExecutionHistoryListener
       โ”‚                                      โ”‚
       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ IJobManagementService โ—„โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                      โ”‚
           โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
           โ–ผ                     โ–ผ
     Dashboard UI           REST api/quartz

3. NuGet Packages

Package Role Required
EasyCore.Quartz Core, REST, History โœ…
EasyCore.Quartz.Dashboard English ops dashboard + Basic Auth Optional
EasyCore.Quartz.MySql MySQL store + schema bootstrap Optional
EasyCore.Quartz.SqlServer SQL Server store + schema bootstrap Optional
EasyCore.Quartz.PostgreSql PostgreSQL store + schema bootstrap Optional
EasyCore.Quartz.Oracle Oracle store + schema bootstrap Optional

4. Database Comparison

Capability In-Memory MySQL SQL Server PostgreSQL Oracle
Package Core only .MySql .SqlServer .PostgreSql .Oracle
Persistence โŒ โœ… โœ… โœ… โœ…
Clustering โŒ โœ… โœ… โœ… โœ…
AutoCreateSchema โ€” โœ… โœ… โœ… โœ…
Table prefix โ€” QRTZ_ QRTZ_ QRTZ_ QRTZ_
Typical use Local trial Common Linux stack Enterprise Windows Cloud / open source Legacy enterprise

4.1 Decision Tree

Need persistence / multi-node?
โ”œโ”€โ”€ No  โ†’ In-Memory (WebApp.Quartz.InMemory)
โ””โ”€โ”€ Yes โ†’ Pick your existing database
        โ”œโ”€โ”€ MySQL / MariaDB โ†’ EasyCore.Quartz.MySql
        โ”œโ”€โ”€ SQL Server โ†’ EasyCore.Quartz.SqlServer
        โ”œโ”€โ”€ PostgreSQL โ†’ EasyCore.Quartz.PostgreSql
        โ””โ”€โ”€ Oracle โ†’ EasyCore.Quartz.Oracle

5. Requirements

Item Requirement
.NET 8.0+
Host ASP.NET Core (Web / API)
Quartz.NET 3.14 (brought by core package)
Database Optional; required only for persistence

6. Installation

dotnet add package EasyCore.Quartz
dotnet add package EasyCore.Quartz.Dashboard

# pick one as needed
dotnet add package EasyCore.Quartz.MySql
dotnet add package EasyCore.Quartz.SqlServer
dotnet add package EasyCore.Quartz.PostgreSql
dotnet add package EasyCore.Quartz.Oracle

7. Quick Start (3 minutes)

7๏ธโƒฃ.1๏ธโƒฃ Define a job

using EasyCore.Quartz;
using Quartz;

[EasyCoreCron("0/10 * * * * ?")]
[EasyCoreDisallowConcurrentExecution]
public sealed class SampleJob : IEasyCoreJob
{
    private readonly ILogger<SampleJob> _logger;
    public SampleJob(ILogger<SampleJob> logger) => _logger = logger;

    public Task Execute(IJobExecutionContext context)
    {
        _logger.LogInformation("SampleJob running at {Time}", DateTimeOffset.Now);
        return Task.CompletedTask;
    }
}

Disable without deleting code:

[EasyCoreDisableJob]
[EasyCoreCron("0 0 * * * ?")]
public sealed class DisabledJob : IEasyCoreJob
{
    public Task Execute(IJobExecutionContext context) => Task.CompletedTask;
}

7๏ธโƒฃ.2๏ธโƒฃ Register services (including dashboard)

// Reference EasyCore.Quartz.Dashboard
builder.Services.AddEasyCoreQuartz(options =>
{
    options.AddAssemblyFrom<SampleJob>();
    options.TimeZoneOffsetHours = +8;
    options.AutoCreateSchema = true;

    // RAM by default. For persistence, uncomment one:
    // options.UseMySql(m => m.ConnectionString = "...");
    // options.UseSqlServer(s => s.ConnectionString = "...");
    // options.UsePostgreSql(p => p.ConnectionString = "...");
    // options.UseOracle(o => o.ConnectionString = "...");

    // Dashboard URL = app base URL + PathMatch
    // No app.UseEasyCoreQuartzDashboard(...) needed
    options.UseEasyCoreQuartzDashboard(dash =>
    {
        dash.PathMatch = "/easy-quartz";
        dash.Username = "admin";
        dash.Password = "admin123";
    });
});

Open: http://localhost:<port>/easy-quartz/ (browser prompts for username/password)


8. Attributes & Options

Attribute / Option Description
IEasyCoreJob Marker interface (extends Quartz IJob)
[EasyCoreCron] Cron, JobKey, JobGroup, Misfire, RequestRecovery
[EasyCoreDisableJob] Skip auto-registration
[EasyCoreDisallowConcurrentExecution] Prevent overlapping runs
AddAssembly / AddAssemblyFrom<T> Explicit discovery
AutoCreateSchema Idempotent DDL on startup (disable in prod)
HistoryCapacity In-memory history ring buffer size (default 200); Overview success/failure counts are window stats
HttpJobTimeout HTTP job timeout (default 30s)
HttpJobBlockPrivateNetworks Default true โ€” blocks loopback/private/metadata hosts
HttpJobAllowedHosts HTTP job host allow-list (e.g. localhost)
TablePrefix Default QRTZ_ (must match DDL)
MaxConcurrency Thread pool size; 0 = auto

9. Dashboard (English UI)

9.1 Preview

dashboard-preview

9.2 Pages

Page Icon Capabilities
Overview ๐Ÿ“Š Scheduler status, job/trigger counts, failure stats
Jobs ๐Ÿ“‹ List; Pause / Resume / Trigger / Delete / Edit Cron / Detail
Recurring ๐Ÿ” Cron jobs only
Executing โšก Currently running jobs
HTTP Jobs ๐ŸŒ Create / update HTTP invoke jobs
History ๐Ÿ“œ Recent executions (node-local memory)
Servers ๐Ÿ–ฅ๏ธ Scheduler name / InstanceId / Store

โš ๏ธ History is a process-local ring buffer. Overview success/failure counts reflect the current window only (not lifetime totals) and are not shared across nodes.

9.3 Authorization (HTTP Basic Auth)

options.UseEasyCoreQuartzDashboard(dash =>
{
    dash.PathMatch = "/easy-quartz"; // full URL = app base + this path
    dash.Username = "admin";         // required
    dash.Password = "admin123";      // required
});
Option Description
PathMatch Relative path (default /easy-quartz)
Username / Password Basic Auth credentials (required; middleware auto-mounted)
BasicAuthAuthorizationFilter Enabled by default
LocalRequestsOnlyAuthorizationFilter Optional; append to dash.Authorization
Custom IEasyCoreQuartzAuthorizationFilter Replace or stack for production

10. REST API

Base path: api/quartz

Method Path Description
GET /overview Overview
GET /jobs All jobs
GET /jobs/{group}/{name} Job detail
GET /recurring Cron jobs
GET /executing Executing jobs
GET /history?take=100 History
PUT /jobs/{group}/{name}/pause Pause
PUT /jobs/{group}/{name}/resume Resume
PUT /jobs/{group}/{name}/cron?cron=... Update cron
DELETE /jobs/{group}/{name} Delete
POST /jobs/{group}/{name}/trigger Trigger now
POST /http-jobs Add/update HTTP job

11. HTTP Jobs

Create via Dashboard HTTP Jobs or REST:

{
  "jobName": "PingApi",
  "jobGroup": "DEFAULT",
  "url": "https://example.com/demo/ping",
  "method": "GET",
  "cron": "0/30 * * * * ?",
  "headers": { "X-Trace": "demo" },
  "body": "",
  "description": "Health ping"
}
Capability Notes
Method GET / POST / PUT / DELETE / PATCH (case-insensitive)
Body JSON validated for POST/PUT/PATCH
Timeout HttpJobTimeout (default 30s)
SSRF Blocks loopback/private/link-local/metadata by default; allow via HttpJobAllowedHosts
Failure Non-2xx โ‡’ exception โ‡’ History failure

To call a local demo API, allow the host explicitly:

options.HttpJobAllowedHosts.Add("localhost");
options.HttpJobAllowedHosts.Add("127.0.0.1");

12. Database Configuration

All providers use table prefix QRTZ_.

๐Ÿฌ MySQL

options.UseMySql(mysql =>
{
    mysql.ConnectionString =
        "server=localhost;port=3306;user id=root;password=***;database=EasyCoreQuartz;";
});

๐ŸŸฆ SQL Server

options.UseSqlServer(sql =>
{
    sql.ConnectionString =
        "Server=.;Database=EasyCoreQuartz;User Id=sa;Password=***;TrustServerCertificate=True;";
});

๐Ÿ˜ PostgreSQL

options.UsePostgreSql(pg =>
{
    pg.ConnectionString =
        "Host=localhost;Port=5432;Database=EasyCoreQuartz;Username=postgres;Password=***";
});

๐Ÿ”ถ Oracle

options.UseOracle(ora =>
{
    ora.ConnectionString =
        "User Id=quartz;Password=***;Data Source=localhost:1521/ORCL";
});

Production DDL tip

options.AutoCreateSchema = false; // disable auto DDL in production

Apply official Quartz scripts (or freeze scripts generated in staging) through your migration pipeline.


13. Clustering & Concurrency

Option Default Description
CheckinInterval 5s Cluster check-in interval
CheckinMisfireThreshold 10s Check-in misfire threshold
MaxConcurrency 20 Thread pool; 0 = auto

Configuring any persistent provider enables Quartz clustering.

Prevent overlapping execution:

[EasyCoreDisallowConcurrentExecution]
[EasyCoreCron("0/5 * * * * ?")]
public sealed class ExclusiveJob : IEasyCoreJob { /* ... */ }

14. Demo Projects

Project Store Port Command
WebApp.Quartz.InMemory RAM 5101 dotnet run --project demo/WebApp.Quartz.InMemory
WebApp.Quartz.MySql MySQL 5102 dotnet run --project demo/WebApp.Quartz.MySql
WebApp.Quartz.SqlServer SQL Server 5103 dotnet run --project demo/WebApp.Quartz.SqlServer
WebApp.Quartz.PostgreSql PostgreSQL 5104 dotnet run --project demo/WebApp.Quartz.PostgreSql
WebApp.Quartz.Oracle Oracle 5105 dotnet run --project demo/WebApp.Quartz.Oracle

Each demo has its own Jobs/SampleJob.cs โ€” open and edit locally, no cross-project reference.

dotnet run --project demo/WebApp.Quartz.InMemory
# open http://localhost:5101/easy-quartz

For DB demos, update ConnectionStrings:Quartz in the corresponding appsettings.json first.


15. Migrating from older versions

8.0.0 is a breaking release (relative to earlier Quarzt* naming):

Older 8.0
QuarztOptions EasyCoreQuartzOptions
api/Quarzt api/quartz
Typo Quarzt Corrected everywhere
Scan all BaseDirectory DLLs EntryAssembly + AddAssembly
Swallowed job exceptions Log and rethrow
Prefix qrtz_ Unified QRTZ_
Mixed licenses MIT

16. Production Checklist

  • Use a strong dashboard password (never ship demo credentials publicly)
  • Set AutoCreateSchema = false with reviewed migrations
  • Keep connection strings in a secret store
  • Monitor logs and History window failure counts (not lifetime totals)
  • HTTP jobs: review HttpJobAllowedHosts / egress policy; do not casually disable private-network blocking
  • Set MaxConcurrency explicitly under heavy load
  • Validate cron expressions before deploy
  • Multi-node setups must share the same store and table prefix

17. FAQ

Q: Dashboard returns 401?
A: The browser prompts for Basic Auth. Use the configured Username / Password. Enabling the dashboard without credentials throws at startup.

Q: Does RAM mode include the dashboard?
A: Yes. Reference EasyCore.Quartz.Dashboard and call options.UseEasyCoreQuartzDashboard(...).

Q: Why is History different across nodes?
A: History is a process-local ring buffer; Overview success/failure counts cover the current window only. Use your logging/audit stack for cross-node history.

Q: HTTP job to localhost is rejected?
A: SSRF protection is on by default. Add the host to options.HttpJobAllowedHosts, or disable HttpJobBlockPrivateNetworks only in controlled environments.

Q: Does default Method=GET fail validation?
A: No. Validation is case-insensitive in 8.0.

Q: How do I scan only my business assembly?
A: options.AddAssemblyFrom<YourJob>() or options.AddAssembly(asm).


18. License

MIT โ€” see LICENSE.


๐Ÿค Contributing

  1. Fork and create a feature branch
  2. Add tests under tests/EasyCore.Quartz.Tests
  3. Run dotnet test and dotnet build EasyCore.Quartz.sln
  4. Open a pull request

Issues and PRs are welcome ๐Ÿš€

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (5)

Showing the top 5 NuGet packages that depend on EasyCore.Quartz:

Package Downloads
EasyCore.Quartz.SqlServer

SQL Server persistence provider for EasyCore.Quartz (auto schema bootstrap + clustering).

EasyCore.Quartz.MySql

MySQL persistence provider for EasyCore.Quartz (auto schema bootstrap + clustering).

EasyCore.Quartz.Dashboard

English ops dashboard for EasyCore.Quartz with Basic Auth and auto middleware mounting.

EasyCore.Quartz.Oracle

Oracle persistence provider for EasyCore.Quartz (auto schema bootstrap + clustering).

EasyCore.Quartz.PostgreSql

PostgreSQL persistence provider for EasyCore.Quartz (auto schema bootstrap + clustering).

GitHub repositories

This package is not used by any popular GitHub repositories.