ToolWheel.Extensions.JobManager
1.0.1
dotnet add package ToolWheel.Extensions.JobManager --version 1.0.1
NuGet\Install-Package ToolWheel.Extensions.JobManager -Version 1.0.1
<PackageReference Include="ToolWheel.Extensions.JobManager" Version="1.0.1" />
<PackageVersion Include="ToolWheel.Extensions.JobManager" Version="1.0.1" />
<PackageReference Include="ToolWheel.Extensions.JobManager" />
paket add ToolWheel.Extensions.JobManager --version 1.0.1
#r "nuget: ToolWheel.Extensions.JobManager, 1.0.1"
#:package ToolWheel.Extensions.JobManager@1.0.1
#addin nuget:?package=ToolWheel.Extensions.JobManager&version=1.0.1
#tool nuget:?package=ToolWheel.Extensions.JobManager&version=1.0.1
ToolWheel.Extensions.JobManager
Core runtime library for the ToolWheel Job Manager. Provides default implementations of the abstractions, the DI registration entry point and the middleware pipeline.
Package Info
| Property | Value |
|---|---|
| Target Framework | net8.0 |
| NuGet Package ID | ToolWheel.Extensions.JobManager |
| Project Reference | ToolWheel.Extensions.JobManager.Abstractions |
DI Registration
Callback style
var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddJobManager(configure =>
{
configure.AddExecutionCondition<MyCondition>();
configure.AddMiddleware<AuditMiddleware>();
configure.ConfigureServices(svc => svc.AddSingleton<IAuditLog, FileAuditLog>());
configure.ConfigureJobs(jobs =>
{
var worker = new ReportWorker();
jobs.Add("daily-report", worker.Generate)
.Name("Daily Report")
.Description("Generates the daily sales report")
.Enabled();
});
});
Startup class style
builder.Services.AddJobManager<MyStartup>();
public class MyStartup : JobManagerStartup
{
public override void ConfigureJobManager(IJobManagerConfigurationBuilder configure)
{
configure.AddMiddleware<AuditMiddleware>();
}
public override void ConfigureJobs(IJobDescriptionCollection collection)
{
var worker = new ReportWorker();
collection.Add("daily-report", worker.Generate)
.Name("Daily Report")
.Enabled();
}
}
Storage Implementations
The core package provides in-memory storage implementations that can be replaced with custom persistence layers via DI.
InMemoryJobStorage
Default implementation of IJobStorage. Maintains an in-memory ConcurrentDictionary of registered jobs.
InMemoryJobTaskStorage
Default implementation of IJobTaskStorage. Tracks all active and completed job tasks in memory.
InMemoryJobTaskJournalStorage
Default implementation of IJobTaskJournalStorage. Stores journal entries for each job task in memory.
InMemoryExtensionOptionStorage
Default implementation of IExtensionOptionStorage. Provides a simple key-value store for extension data.
Custom Storage Example:
// Register a custom storage implementation
builder.Services.AddJobManager(configure =>
{
configure.ConfigureServices(services =>
{
services.AddSingleton<IJobStorage, DatabaseJobStorage>();
services.AddSingleton<IJobTaskStorage, DatabaseJobTaskStorage>();
services.AddSingleton<IJobTaskJournalStorage, DatabaseJournalStorage>();
});
});
Services
JobService
Default implementation of IJobService. Maintains an in-memory ConcurrentDictionary<string, IJob> registry and delegates execution to IJobTaskService.
After a job is registered, Add iterates the features on the IJobDescription and calls IJobManagerFeature.Apply(serviceProvider, jobDescription, job) on each one. This is the single, unified hook for extension features to register per-job data with their runtime services (trigger schedules, retry policies, �). It works identically for jobs registered at startup and for jobs added dynamically at runtime.
var jobService = serviceProvider.GetRequiredService<IJobService>();
// Add � Apply is called for every attached feature
IJob job = jobService.Add(jobDescription);
// Add dynamically at runtime
IJob job = jobService.Add(worker.DoWork, b => b
.Name("Dynamic Job")
.WithFeature<TriggerFeature>(f => f.Add(new IntervalTrigger(TimeSpan.FromMinutes(5)))));
IJob? found = jobService.FindById("my-job");
IJob read = jobService.ReadById("my-job"); // throws KeyNotFoundException when missing
IEnumerable<IJob> all = jobService.ReadAll();
IJobTask task = await jobService.ExecuteAsync(job);
bool removed = jobService.Remove(job);
JobTaskService
Default implementation of IJobTaskService. Creates JobTask instances, delegates execution to IJobTaskExecutionService and tracks active tasks.
CancelAllAndWaitAsync signals cancellation on all tracked tasks and awaits their completion � called during graceful shutdown.
JobTaskExecutionService
Builds the middleware pipeline for a job task and executes it. Before the pipeline starts, execution conditions are evaluated via IJobExecutionEvaluatorService. If any condition returns not-ready, the task status is set to NotReady and execution is skipped.
Built-in pipeline steps (innermost last):
JobTaskTargetObjectMiddleware� resolvesTargetObjectfrom DI when it isnull.- The final step invokes
IJob.TargetMethod.
JobExecutionEvaluatorService
Evaluates all registered execution conditions without starting a task and returns the aggregated JobConditionStatus. Useful for pre-flight checks.
var evaluator = serviceProvider.GetRequiredService<IJobExecutionEvaluatorService>();
var status = await evaluator.EvaluateAsync(job);
if (status.Status == JobConditionStatusEnum.NotReady)
Console.WriteLine($"Job not ready: {status.Message}");
Built-in Middleware and Conditions
| Type | Purpose |
|---|---|
JobTaskTargetObjectMiddleware |
Resolves the target object from DI. When IJob.UseSingletonInstance is true, the instance is cached and reused across executions. |
JobConditionController |
Default IExecutionConditionController � iterates all conditions and short-circuits on the first not-ready result. |
JobEnabledCondition |
Blocks execution when IJob.Enabled is false. |
Singleton Instances
When a job is configured with .AsSingleton(), JobTaskTargetObjectMiddleware creates the target instance once on the first execution and caches it for all subsequent executions. Without .AsSingleton() a fresh instance is resolved from DI on every execution.
jobs.Add<MyWorker>(w => w.Process)
.Name("Singleton Worker")
.AsSingleton();
Auto Feature Configuration
AddJobManager scans all loaded assemblies, finds every non-abstract IAutoFeatureConfigurator implementation and calls AutoConfigure(builder) on each. Configurators register services only (middleware, conditions, singletons).
Per-job feature data flows through a separate path:
Startup: AddJobManager ? IAutoFeatureConfigurator.AutoConfigure (services)
? JobService.Add ? IJobManagerFeature.Apply (per-job data)
Runtime: JobService.Add ? IJobManagerFeature.Apply (per-job data)
Implementing a custom feature
// 1. Feature � override Apply to push per-job data into a runtime service
public class NotifyFeature : IJobManagerFeature
{
public string WebhookUrl { get; set; } = string.Empty;
public void Apply(IServiceProvider serviceProvider, IJobDescription jobDescription, IJob job)
{
serviceProvider.GetRequiredService<INotifyService>()
.Register(job.Id, WebhookUrl);
}
}
// 2. Configurator � registers the runtime service once
public class NotifyConfigurator : IAutoFeatureConfigurator
{
public void AutoConfigure(IJobManagerConfigurationBuilder builder)
{
builder.ConfigureServices(services =>
services.AddSingleton<INotifyService, NotifyService>());
}
}
// 3. Usage
jobs.Add("my-job", worker.Run)
.WithFeature<NotifyFeature>(f => f.WebhookUrl = "https://hooks.example.com/notify");
Job Task Journal
Each IJobTask exposes a Journal of JobTaskJournalEntry records. When a per-job logger is configured via .WithLogger(...), journal entries are forwarded to it through JobTaskJournalLoggerAdapter.
| Product | Versions 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. |
-
net8.0
- ToolWheel.Extensions.JobManager.Abstractions (>= 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.