ToolWheel.Extensions.JobManager
1.0.0-preview6
dotnet add package ToolWheel.Extensions.JobManager --version 1.0.0-preview6
NuGet\Install-Package ToolWheel.Extensions.JobManager -Version 1.0.0-preview6
<PackageReference Include="ToolWheel.Extensions.JobManager" Version="1.0.0-preview6" />
<PackageVersion Include="ToolWheel.Extensions.JobManager" Version="1.0.0-preview6" />
<PackageReference Include="ToolWheel.Extensions.JobManager" />
paket add ToolWheel.Extensions.JobManager --version 1.0.0-preview6
#r "nuget: ToolWheel.Extensions.JobManager, 1.0.0-preview6"
#:package ToolWheel.Extensions.JobManager@1.0.0-preview6
#addin nuget:?package=ToolWheel.Extensions.JobManager&version=1.0.0-preview6&prerelease
#tool nuget:?package=ToolWheel.Extensions.JobManager&version=1.0.0-preview6&prerelease
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();
}
}
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 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
- ToolWheel.Extensions.JobManager.Abstractions (>= 1.0.0-preview6)
-
net8.0
- ToolWheel.Extensions.JobManager.Abstractions (>= 1.0.0-preview6)
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.0-preview6 | 52 | 3/26/2026 |
| 1.0.0-preview5 | 53 | 2/21/2026 |
| 1.0.0-preview4 | 49 | 2/19/2026 |