Alveus.JobRunner 0.5.2

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

Alveus.JobRunner

Release Build status

A lightweight, AOT-compatible job runner for executing tasks sequentially with support for dynamic job enqueueing, custom contexts, and comprehensive execution callbacks.

Buy me a Coffee

Features

  • Sequential Execution: Jobs are executed in FIFO order
  • Dynamic Job Enqueueing: Jobs can enqueue additional jobs during execution
  • Custom Context: Pass custom data to all jobs in the sequence
  • Exception Handling: Configure whether to halt or continue on exceptions
  • Execution Callbacks: Hook into job lifecycle events
  • AOT Compatible: Fully supports Native AOT compilation
  • Flexible Job Definition: Define jobs via classes or inline delegates

Installation

dotnet add package Alveus.JobRunner

Quick Start

Using DelegateJob

using Alveus.JobRunner;

var runner = new JobRunner<MyContext>();

// Add jobs using delegates
runner.Enqueue(new DelegateJob<MyContext>(
    async (queue, context, ct) =>
    {
        Console.WriteLine("Job 1 executing");

        // Enqueue additional jobs dynamically
        queue.Enqueue(new DelegateJob<MyContext>(
            async (q, ctx, c) => Console.WriteLine("Job 3 executing"),
            "Dynamic Job"
        ));
    },
    "Job 1"
));

runner.Enqueue(new DelegateJob<MyContext>(
    async (queue, context, ct) => Console.WriteLine("Job 2 executing"),
    "Job 2"
));

// Execute all jobs
var context = new MyContext();
await runner.ExecuteAsync(context);

Using Custom Job Classes

using Alveus.JobRunner;

[JobName("Send Email")]
public class SendEmailJob : IJob<EmailContext>
{
    public async Task ExecuteAsync(IJobQueue<EmailContext> queue, EmailContext context, CancellationToken cancellationToken)
    {
        await SendEmailAsync(context.Recipient, context.Message);

        // Optionally enqueue follow-up jobs
        queue.Enqueue(new LogEmailSentJob());
    }
}

var runner = new JobRunner<EmailContext>();
runner.Enqueue(new SendEmailJob());
await runner.ExecuteAsync(new EmailContext
{
    Recipient = "user@example.com",
    Message = "Hello!"
});

Exception Handling

Halt on Exception (Default)

var runner = new JobRunner<string>();
runner.Enqueue(new DelegateJob<string>(async (q, ctx, ct) => throw new Exception()));

// Throws exception and stops execution
await runner.ExecuteAsync("context", haltOnException: true);

Continue on Exception

var runner = new JobRunner<string>();
runner.Enqueue(new DelegateJob<string>(async (q, ctx, ct) => throw new Exception()));
runner.Enqueue(new DelegateJob<string>(async (q, ctx, ct) => Console.WriteLine("Still executing")));

// Continues executing remaining jobs after exception
await runner.ExecuteAsync("context", haltOnException: false);

Execution Callbacks

OnJobExecuting

var runner = new JobRunner<string>();

runner.OnJobExecuting += context =>
{
    Console.WriteLine($"Executing job {context.JobIndex + 1}/{context.TotalJobs}");
    if (context.JobName != null)
    {
        Console.WriteLine($"Job name: {context.JobName}");
    }
};

runner.Enqueue(new DelegateJob<string>(async (q, ctx, ct) => { }, "My Job"));
await runner.ExecuteAsync("context");

OnJobException

var runner = new JobRunner<string>();

runner.OnJobException += (context, exception) =>
{
    Console.WriteLine($"Job {context.JobIndex} failed: {exception.Message}");
    // Log to monitoring service, send alerts, etc.
};

runner.Enqueue(new DelegateJob<string>(async (q, ctx, ct) => throw new Exception("Oops")));
await runner.ExecuteAsync("context", haltOnException: false);

Job Naming

Using JobNameAttribute

[JobName("Process Payment")]
public class ProcessPaymentJob : IJob<PaymentContext>
{
    public async Task ExecuteAsync(IJobQueue<PaymentContext> queue, PaymentContext context, CancellationToken cancellationToken)
    {
        // Process payment
    }
}

Using DelegateJob Constructor

runner.Enqueue(new DelegateJob<string>(
    async (q, ctx, ct) => { /* work */ },
    "My Named Job"
));

Advanced Usage

Dynamic Job Chaining

var runner = new JobRunner<ProcessContext>();

runner.Enqueue(new DelegateJob<ProcessContext>(
    async (queue, context, ct) =>
    {
        var items = await FetchItemsAsync();

        // Dynamically enqueue a job for each item
        foreach (var item in items)
        {
            queue.Enqueue(new ProcessItemJob(item));
        }
    },
    "Fetch and Queue Items"
));

await runner.ExecuteAsync(new ProcessContext());

Progress Tracking

var runner = new JobRunner<string>();
var progress = new Progress();

runner.OnJobExecuting += context =>
{
    progress.Report(context.JobIndex, context.TotalJobs);
};

// Add jobs...
await runner.ExecuteAsync("context");

Cancellation Support

var runner = new JobRunner<string>();
var cts = new CancellationTokenSource();

// Add jobs...

// Cancel after 5 seconds
cts.CancelAfter(TimeSpan.FromSeconds(5));

try
{
    await runner.ExecuteAsync("context", cancellationToken: cts.Token);
}
catch (OperationCanceledException)
{
    Console.WriteLine("Execution was cancelled");
}

API Reference

IJobRunner<TContext>

  • void Enqueue(IJob<TContext> job) - Enqueues a job for execution
  • Task ExecuteAsync(TContext context, bool haltOnException = true, CancellationToken cancellationToken = default) - Executes all enqueued jobs
  • event JobExecutingCallback<TContext>? OnJobExecuting - Fires before each job executes
  • event JobExceptionCallback<TContext>? OnJobException - Fires when a job throws an exception

IJob<TContext>

  • Task ExecuteAsync(IJobQueue<TContext> queue, TContext context, CancellationToken cancellationToken) - Executes the job

JobExecutionContext<TContext>

  • IJob<TContext> Job - The job being executed
  • string? JobName - The name of the job (from attribute or constructor)
  • int JobIndex - Zero-based index of the job
  • int TotalJobs - Total number of jobs in the queue

License

Refer to LICENSE document for license information.

Contributing

Copyright (c) Alveus Dev (https://alveus.dev). All rights reserved.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  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 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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.

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
0.5.2 242 12/27/2025
0.5.1 165 12/26/2025
0.5.0 170 12/26/2025