NOBS.JobSystem.Hosting
1.0.1
See the version list below for details.
dotnet add package NOBS.JobSystem.Hosting --version 1.0.1
NuGet\Install-Package NOBS.JobSystem.Hosting -Version 1.0.1
<PackageReference Include="NOBS.JobSystem.Hosting" Version="1.0.1" />
<PackageVersion Include="NOBS.JobSystem.Hosting" Version="1.0.1" />
<PackageReference Include="NOBS.JobSystem.Hosting" />
paket add NOBS.JobSystem.Hosting --version 1.0.1
#r "nuget: NOBS.JobSystem.Hosting, 1.0.1"
#:package NOBS.JobSystem.Hosting@1.0.1
#addin nuget:?package=NOBS.JobSystem.Hosting&version=1.0.1
#tool nuget:?package=NOBS.JobSystem.Hosting&version=1.0.1
NOBS.JobSystem
A lightweight, database-backed, dependency-injection friendly job scheduling system for .NET applications. It provides CRON-based scheduling, job chaining, and a persistent execution history with an optional Blazor-based monitoring UI.
Key Features
- Stable Job Identity: Use the
[JobName]
attribute to assign a persistent identifier to your jobs, preventing history loss when you refactor code. - CRON Scheduling: Define recurring jobs using standard CRON expressions.
- Job Chaining: Create workflows by specifying continuation jobs on success or failure.
- Persistent History: Automatically tracks the last successful run time for each job in a database, ensuring schedules resume correctly after an application restart.
- DI-First Design: Jobs are resolved from the service container, giving them access to all registered application services.
- Error Handling: Configure specific jobs to run when a preceding job fails or throws an exception.
- Optional Monitoring UI: A clean, lightweight Blazor UI to monitor job statuses, last run times, and next scheduled runs.
- EF Core Migrations: The database schema for storing job history is managed automatically via Entity Framework Core migrations.
Packages
The system is distributed across three NuGet packages:
Package | Description |
---|---|
NOBS.JobSystem |
The core library containing the job orchestrator and scheduling logic. |
NOBS.JobSystem.UI |
The Blazor-based monitoring UI. |
NOBS.JobSystem.Hosting |
A meta-package for easily installing and configuring both the core and UI. |
Installation
Install the hosting package for the quickest setup in an ASP.NET Core application.
dotnet add package NOBS.JobSystem.Hosting
Or, install the packages individually if you do not require the UI.
dotnet add package NOBS.JobSystem
Quick Start
1. Define Jobs with Stable Names
Create classes that implement the IJob
interface. It is strongly recommended to assign a stable, unique name to every job using the [JobName]
attribute.
// src/MyWebApp/Jobs/HelloWorldJob.cs
using NOBS.JobSystem.Abstractions;
[JobName("hello-world-greeter")]
public class HelloWorldJob(ILogger<HelloWorldJob> logger) : IJob
{
public Task<JobExecutionResult> ExecuteAsync(CancellationToken cancellationToken)
{
logger.LogInformation("Hello from a scheduled job at {UtcNow}!", DateTime.UtcNow);
return Task.FromResult(JobExecutionResult.Success());
}
}
2. Configure the Job System
In your Program.cs
, add the job system, configure the database connection, and register your jobs. All jobs, including those used only for chaining, must be registered.
// src/MyWebApp/Program.cs
using NOBS.JobSystem.Hosting;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("JobDbConnection");
// Add services to the container.
builder.Services.AddHostedJobSystem(
options =>
{
options.ConnectionString = connectionString;
options.PollingFrequency = TimeSpan.FromSeconds(30); // Optional: Default is 1 minute
},
registry =>
{
// Register a scheduled job
registry.AddJob<HelloWorldJob>("* * * * *");
// Register jobs that are only used for chaining or error handling
registry.AddJob<ErrorLoggingJob>();
registry.AddJob<InitialJob>();
// Configure a scheduled job with an error handler
registry.AddJob<InitialJob>("0 * * * *") // Run hourly
.OnError<ErrorLoggingJob>(); // Run ErrorLoggingJob if InitialJob fails
}
);
var app = builder.Build();
// Map the UI endpoint
app.MapHostedJobSystemUI();
app.Run();
3. Provide a Connection String
Ensure the connection string is present in your appsettings.json
.
{
"ConnectionStrings": {
"JobDbConnection": "Server=(localdb)\\mssqllocaldb;Database=MyJobSystemDb;Trusted_Connection=True;"
}
}
The system will automatically create and migrate the database on startup to add its ExecutionHistory
table.
Advanced Usage
Job Chaining
Jobs can trigger other jobs upon completion.
JobExecutionResult.Success(Type nextJob)
: Queues a new job immediately if the current job succeeds.JobExecutionResult.Failure(Type nextJob)
: Queues a new job immediately if the current job returns a failure result..OnError<TErrorJob>()
: A declarative way to specify an error-handling job if the configured job throws an unhandled exception.
Important: All jobs in a chain must be registered with the JobRegistry
in Program.cs
to be available for dependency injection.
// Job definitions with stable names
[JobName("data-processor")]
public class DataProcessingJob : IJob
{
public async Task<JobExecutionResult> ExecuteAsync(CancellationToken cancellationToken)
{
bool success = await DoSomeWorkAsync();
return success
? JobExecutionResult.Success(typeof(NotificationJob))
: JobExecutionResult.Failure(typeof(CleanupJob));
}
}
[JobName("user-notifier")]
public class NotificationJob : IJob { /* ... */ }
[JobName("cleanup-on-failure")]
public class CleanupJob : IJob { /* ... */ }
[JobName("critical-failure-alert")]
public class CriticalFailureAlertJob : IJob { /* ... */ }
// In Program.cs
registry.AddJob<NotificationJob>();
registry.AddJob<CleanupJob>();
registry.AddJob<CriticalFailureAlertJob>();
registry.AddJob<DataProcessingJob>("0 2 * * *") // Run daily at 2 AM
.OnError<CriticalFailureAlertJob>(); // Run this if DataProcessingJob throws
Stable Job Identity
The job name is used as the primary key in the database to track execution history. By default, the system uses the job's class name (e.g., DataProcessingJob
). This is brittle; if you rename or move the class, its execution history will be lost, and it will be treated as a new job.
The [JobName]
attribute decouples the job's identity from its implementation details. Once a job is in production, its [JobName]
should be considered immutable.
The system will throw an exception on startup if it detects two jobs registered with the same name.
Building From Source
- Clone the repository:
git clone https://github.com/scippo97sensibleproductions/NOBS.JobSystem.git
- Navigate to the solution directory:
cd NOBS.JobSystem
- Build the solution:
dotnet build
License
This project is licensed under the MIT License. See the LICENSE file for details.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net10.0 is compatible. 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. |
-
net10.0
- NOBS.JobSystem (>= 1.0.1)
- NOBS.JobSystem.UI (>= 1.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.