TCM.Tasks 1.0.21

dotnet add package TCM.Tasks --version 1.0.21
                    
NuGet\Install-Package TCM.Tasks -Version 1.0.21
                    
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="TCM.Tasks" Version="1.0.21" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="TCM.Tasks" Version="1.0.21" />
                    
Directory.Packages.props
<PackageReference Include="TCM.Tasks" />
                    
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 TCM.Tasks --version 1.0.21
                    
#r "nuget: TCM.Tasks, 1.0.21"
                    
#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 TCM.Tasks@1.0.21
                    
#: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=TCM.Tasks&version=1.0.21
                    
Install as a Cake Addin
#tool nuget:?package=TCM.Tasks&version=1.0.21
                    
Install as a Cake Tool

TCM.Tasks

Distributed task scheduling library for TCM services, built on Quartz.NET. Provides persistent, clustered background job scheduling with auto-discovery of job implementations and a MediatR-based management API.

Features

  • Quartz.NET Integration — Persistent job store backed by SQL Server
  • Kubernetes Clustering — Built-in cluster support for distributed deployments
  • Auto Job Discovery — Automatically discovers and registers all IQuartzJob implementations at startup
  • Cron & Interval Scheduling — Supports standard cron expressions and time-interval triggers
  • Run-Now Support — Trigger any job immediately via MediatR query or REST API
  • Execution Tracking — Records last start, last success, and last failure timestamps per job
  • CQRS API — MediatR commands and queries to create, update, and query scheduled tasks
  • REST API — Optional controllers for CRUD (AddTCMTasksControllers)
  • Lease-Based Clustering — Prevents duplicate execution across nodes via machine-name leasing

Installation

dotnet add package TCM.Tasks

Note: TCM.Tasks depends on TCM.Core. Both packages must be installed.

Requirements

  • .NET 9.0
  • SQL Server (for Quartz persistent store and ScheduleTask table)
  • TCM.Core

Getting Started

Register Services

Tasks uses a dedicated SQL Server database shared by EF (ScheduleTask) and Quartz (qrtz_* tables).

builder.Services.AddTCMTasks(builder.Configuration);

// Or pass connection string and/or app id explicitly
builder.Services.AddTCMTasks(builder.Configuration, myConnectionString, appId: "MyApp");
Registration DbContext Migrations
AddTCMTasks TasksDbContext ScheduleTask

Each host application should set TASK_APP_ID so tasks and Quartz jobs are isolated when multiple apps share the same database. Legacy rows may keep AppId null until you backfill them manually.

Quartz scheduler instance: tcm-tasks-{appId} (or tcm-tasks-default when unset). Job group: {appId}.BackgroundTask (or BackgroundTask when unset).

HTTP API (controllers)

builder.Services.AddControllers()
    .AddTCMTasksControllers();

Ensure the host configures API versioning (v1.0), same as other TCM APIs.

Method Route Description
GET api/v1/ScheduleTask Paged list
GET api/v1/ScheduleTask/{id} Get by Guid
POST api/v1/ScheduleTask Create
PUT api/v1/ScheduleTask/{id} Update
DELETE api/v1/ScheduleTask/{id} Delete (+ remove Quartz job)
POST api/v1/ScheduleTask/{id}/run-now Execute immediately

TCM.Tasks references TCM.InAppAuth. Controllers use [AppPermission]; handlers apply data scope on ScheduleTask via IScopedEntity.OrgUnitId.

builder.Services.AddInAppAuthentication(builder.Configuration);
builder.Services.AddTCMTasks(builder.Configuration);

builder.Services.AddControllers()
    .AddInAppAuthControllers()
    .AddTCMTasksControllers();

Align app ids: IN_APP_AUTH_APP_ID and TASK_APP_ID should resolve to the same value (e.g. Tasks → resource slug tasks:schedule-task).

Step Action
1 Run migrations: InAppAuth + Tasks (AddScheduleTaskOrgUnitId)
2 POST /api/v1/Resource/sync — register schedule-task + run-now
3 Grant role permissions in admin UI
4 Optional: POST /api/v1/DataScope/MigrateAllowOwnOnly
5 Configure RoleResourceDataScope; set enforcement OffLogOnlyEnforce

Records without OrgUnitId are only visible when scope is All. On create, OrgUnitId defaults to the user's primary org; returns 400 if missing (unless scope is All).

Connection string

Same database for EF and Quartz. Resolution order:

  1. connectionString argument to AddTCMTasks (if provided)
  2. Otherwise TASK_CONNTECTION_STRING:
    • Development: appsettings.json key TASK_CONNTECTION_STRING
    • Other environments: environment variable TASK_CONNTECTION_STRING, then appsettings fallback

appsettings.json (Development):

{
  "TASK_CONNTECTION_STRING": "Server=...;Database=TCM.Tasks;User Id=...;Password=...;TrustServerCertificate=True",
  "TASK_APP_ID": "MyApp"
}

Production / container:

TASK_CONNTECTION_STRING="Server=...;Database=TCM.Tasks;..."
TASK_APP_ID="MyApp"

EF migrations

Use TasksDbContext for all migrations.

Package Manager Console (default project = TCM.Tasks or migrations project):

Add-Migration AddScheduleTasks -Context TasksDbContext -Project TCM.Tasks -StartupProject TCM.Tasks
Update-Database -Context TasksDbContext -Project TCM.Tasks -StartupProject TCM.Tasks

dotnet ef:

dotnet ef migrations add AddScheduleTasks --project TCM.Tasks --startup-project TCM.Tasks --context TasksDbContext
dotnet ef database update --project TCM.Tasks --startup-project TCM.Tasks --context TasksDbContext

Design-time: TASK_CONNTECTION_STRING in appsettings.json of the startup project (or env var).

Initialize Quartz Tables

On first run, call DatabaseExtension.InitializeAsync() to create the required Quartz SQL Server tables. The SQL script is embedded in the library.

await app.Services.InitializeTaskDatabaseAsync();

Define a Job

public class SendReportJob : IQuartzJob
{
    public async Task Execute(IJobExecutionContext context)
    {
        // job logic here
    }

    public async Task Execute(string id, bool checkRun)
    {
        await Execute(id);
    }

    public async Task Execute(string id)
    {
        // run with specific task ID
    }
}

All classes implementing IQuartzJob are auto-discovered at startup and synced with the database.

Manage Jobs via MediatR

await mediator.Send(new CreateScheduleTaskCommand { ... });
await mediator.Send(new UpdateScheduleTaskCommand { Id = taskId, Enabled = false });
var tasks = await mediator.Send(new ScheduleTasksQuery());
await mediator.Send(new ScheduleTaskRunNowQuery { Id = taskId });

Project Structure

TCM.Tasks/
├── Domain/               ScheduleTask, IScheduleTaskDefinition
├── Models/               ScheduleTaskModel
├── Infrastructure/       ScheduleTaskRepository
├── TypeConfigurations/
├── Contexts/             TasksDbContext
├── Command/              Create, Update, Delete
├── Query/                List, Get, RunNow
├── Controllers/v1/       ScheduleTaskController
├── Quartz/               QuartzJobExecute, IQuartzJob
└── Extensions/           AddTCMTasks, UseQuartz

ScheduleTask Entity

Field Description
AppId Host application identifier (nullable for legacy rows; set via TASK_APP_ID)
ScheduleTaskName Display name of the job
Type Fully qualified type name of the IQuartzJob implementation
CronExpression Standard Quartz cron expression (takes priority over interval)
TimeInterval Fallback interval in seconds when no cron expression is set
Enabled Whether the job is active
StopOnError Disable the job automatically on execution failure
LastStartUtc Last time the job started
LastSuccessUtc Last time the job completed successfully
LastNonSuccessEndUtc Last time the job ended with an error
LeasedByMachineName Node currently holding the execution lease (clustering)
LeasedUntilUtc Lease expiry time (clustering)

Key Dependencies

Package Purpose
Quartz.AspNetCore Quartz.NET ASP.NET Core integration
Quartz.Extensions.DependencyInjection DI support for Quartz
Quartz.Serialization.Json JSON job data serialization
TCM.Core Repositories, BaseEntity, TypeFinder, MediatR, etc.
Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  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 is compatible.  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

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.21 91 6/2/2026
1.0.20 82 6/2/2026
1.0.19 105 5/26/2026
1.0.18 88 5/25/2026
1.0.17 88 5/25/2026
1.0.16 87 5/25/2026
1.0.15 92 5/24/2026
1.0.14 106 5/24/2026
1.0.13 87 5/24/2026
1.0.11 93 5/24/2026
1.0.10 91 5/24/2026
1.0.9 105 5/23/2026
1.0.8 106 5/23/2026
1.0.5 95 5/23/2026
1.0.4 89 5/23/2026
1.0.3 115 4/6/2026
1.0.2 107 3/23/2026
1.0.1 105 3/18/2026
1.0.0 101 3/18/2026