Veggerby.Ignition 0.6.0

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

Veggerby.Ignition

A lightweight, extensible startup readiness ("ignition") coordination library for .NET applications. Register ignition signals representing asynchronous initialization tasks (cache warmers, external connections, background services) and await them collectively with rich diagnostics, configurable policies, timeouts, tracing, and health checks.

Features

  • Simple IIgnitionSignal abstraction (name, optional timeout, WaitAsync)
  • Coordinated waiting via IIgnitionCoordinator
  • Global timeout (soft by default) with per-signal overrides
  • Policies: FailFast, BestEffort, ContinueOnTimeout
  • Health check integration (adds ignition-readiness check)
  • Activity tracing (toggle via options)
  • Slow handle logging (top N longest signals)
  • Task and cancellable Task factory adapters (IgnitionSignal.FromTask, FromTaskFactory)
  • Idempotent execution (signals evaluated once, result cached)
  • Execution modes: Parallel (default) or Sequential
  • Optional parallelism limiting via MaxDegreeOfParallelism
  • Cooperative cancellation on global or per-signal timeout

Quick Start

// Program.cs or hosting setup
builder.Services.AddIgnition(options =>
{
    options.GlobalTimeout = TimeSpan.FromSeconds(10);
    options.Policy = IgnitionPolicy.BestEffort; // or FailFast / ContinueOnTimeout
    options.EnableTracing = true; // emits Activity if diagnostics consumed
    options.ExecutionMode = IgnitionExecutionMode.Parallel; // or Sequential
    options.MaxDegreeOfParallelism = 4; // limit concurrency (Parallel mode only)
    options.CancelOnGlobalTimeout = true; // attempt to cancel still-running signals if global timeout hits
    options.CancelIndividualOnTimeout = true; // cancel a signal if its own timeout elapses
});

// Register concrete ignition signals
builder.Services.AddIgnitionSignal(new CustomConnectionSignal());

// Wrap an existing task
builder.Services.AddIgnitionFromTask("cache-warm", cacheWarmTask, timeout: TimeSpan.FromSeconds(5));

// Wrap a cancellable task factory (invoked lazily once)
builder.Services.AddIgnitionFromTask(
    name: "search-index",
    readyTaskFactory: ct => indexBuilder.BuildAsync(ct),
    timeout: TimeSpan.FromSeconds(30));

// Adapt a single service exposing a readiness Task
builder.Services.AddIgnitionFor<MyBackgroundWorker>(w => w.ReadyTask);

// Composite: await all instances of a service type
builder.Services.AddIgnitionForAll<ShardProcessor>(p => p.ReadyTask);

// TaskCompletionSource helpers
_startupReady.Ignited();
_startupReady.IgnitionFailed(ex);

var app = builder.Build();

// Await readiness before starting interactive loop or accepting traffic
await app.Services.GetRequiredService<IIgnitionCoordinator>().WaitAllAsync();

Creating a Custom Signal

public sealed class CustomConnectionSignal : IIgnitionSignal
{
    public string Name => "db-connection";
    public TimeSpan? Timeout => TimeSpan.FromSeconds(8); // optional override

    public async Task WaitAsync(CancellationToken cancellationToken = default)
    {
        // Perform initialization (e.g. open connection, ping server)
        await DatabaseClient.InitializeAsync(cancellationToken);
    }
}

Register it:

services.AddIgnitionSignal<CustomConnectionSignal>();

Policies

Policy Behavior
FailFast Throws if any signal fails (aggregate exceptions).
BestEffort Logs failures, continues startup (default).
ContinueOnTimeout Proceeds when global timeout elapses; logs partial results.

Diagnostics & Results

After ignition completes:

var coord = provider.GetRequiredService<IIgnitionCoordinator>();
var result = await coord.GetResultAsync();
if (result.TimedOut)
{
    // handle degraded startup
}
foreach (var r in result.Results)
{
    Console.WriteLine($"{r.Name}: {r.Status} in {r.Duration.TotalMilliseconds:F0} ms");
}

Health Check

AddIgnition automatically registers a health check named ignition-readiness returning:

  • Healthy: all signals succeeded
  • Degraded: soft global timeout elapsed without per-signal timeouts/failures
  • Unhealthy: one or more signals failed, a hard global timeout (with cancellation) occurred, or exception during evaluation

Tracing

Set EnableTracing = true to emit an Activity named Ignition.WaitAll. Attach listeners via ActivitySource to integrate with OpenTelemetry or other observability pipelines.

Design Notes

  • Thread-safe lazy execution ensures signals run at most once.
  • Global timeout is soft unless cancellation is enabled (see Global Timeout Semantics).
  • Factory-based signals honor cancellation tokens for cooperative shutdown scenarios.
  • Sequential mode enables early fail-fast behavior and reduces resource contention.
  • Per-signal cancellation requires signal implementations to observe passed CancellationToken.

Cancellation Token Semantics for Selectors

The cancellable selector overloads (AddIgnitionFor<TService>(Func<TService, CancellationToken, Task>), AddIgnitionForAll<TService>(Func<TService, CancellationToken, Task>), and scoped variants) receive the cancellation token from the FIRST wait invocation. That token is linked to coordinator-driven cancellations:

  • Hard global timeout (CancelOnGlobalTimeout = true)
  • Per-signal timeout cancellation (CancelIndividualOnTimeout = true)

Because ignition evaluation is idempotent, subsequent calls to IIgnitionCoordinator.WaitAllAsync() reuse already created tasks; the token cannot be changed after the first invocation. Selector implementations should:

  • Avoid capturing ambient tokens elsewhere (use only the provided one)
  • Return promptly or cooperatively observe cancellation (e.g. await Task.Delay(timeout, token))
  • Not block synchronously; always async-await

If you require a fresh cancellation token per consumer, expose a custom IIgnitionSignal instead of using the built-in selector adapters.

Installation

Add a package reference (after publishing):

dotnet nuget add package Veggerby.Ignition

Roadmap Ideas

  • Built-in signals (e.g. HttpEndpointSignal, ChannelDrainSignal)
  • OpenTelemetry semantic conventions integration
  • Structured metrics export (histograms for durations)

License

MIT

Additional Adapters

// Single instance
services.AddIgnitionFor<CachePrimer>(c => c.ReadyTask);

// Composite group
services.AddIgnitionForAll<Consumer>(c => c.ReadyTask, groupName: "Consumer[*]");

// Arbitrary provider-based readiness
services.AddIgnitionFromFactory(
    taskFactory: sp => Task.WhenAll(
        sp.GetRequiredService<PrimaryConnection>().OpenAsync(),
        sp.GetRequiredService<ReplicaConnection>().WarmAsync()),
    name: "datastore-connections");

// TCS helpers
_readyTcs.Ignited();
_readyTcs.IgnitionFailed(new Exception("boom"));

Global Timeout Semantics

Ignition exposes two timeout layers:

  1. Global timeout (GlobalTimeout): A soft deadline unless CancelOnGlobalTimeout = true.
    • Soft (default): Execution continues beyond the elapsed deadline; final result only marked timed out if any signal itself timed out.
    • Hard (cancelling): Outstanding signals receive cancellation; result marked timed out and unfinished signals reported with their names and TimedOut status.
  2. Per-signal timeout (IIgnitionSignal.Timeout): Always enforced; if elapsed the signal is marked TimedOut and optionally cancelled when CancelIndividualOnTimeout = true.

Classification summary:

Scenario Result.TimedOut Signal statuses
Soft global timeout, all eventually succeed False All Succeeded
Soft global timeout, a signal timed out True TimedOut + Succeeded
Hard global timeout (cancel) True TimedOut (unfinished) + any completed
Per-signal timeout only True TimedOut + Succeeded

This model avoids penalizing slow but successful initialization while still enabling an upper bound via opt-in cancellation.

Configuration Examples

// Soft global timeout (default behavior):
services.AddIgnition(o =>
{
    o.GlobalTimeout = TimeSpan.FromSeconds(5); // deadline hint
    o.CancelOnGlobalTimeout = false;           // remain soft (default)
    o.CancelIndividualOnTimeout = false;       // per-signal timeouts won't cancel tasks
});

// Hard global timeout with cancellation:
services.AddIgnition(o =>
{
    o.GlobalTimeout = TimeSpan.FromSeconds(5);
    o.CancelOnGlobalTimeout = true;            // cancel all outstanding signals at deadline
    o.Policy = IgnitionPolicy.ContinueOnTimeout; // choose continuation policy
});

// Mixed: hard global timeout + per-signal timeout cancellation:
services.AddIgnition(o =>
{
    o.GlobalTimeout = TimeSpan.FromSeconds(10);
    o.CancelOnGlobalTimeout = true;            // hard deadline
    o.CancelIndividualOnTimeout = true;        // cancel slow individual signals
    o.ExecutionMode = IgnitionExecutionMode.Parallel;
    o.MaxDegreeOfParallelism = 4;
});

// Defining a per-signal timeout (hard for that signal only):
services.AddIgnitionFromTask(
    name: "search-index",
    readyTaskFactory: ct => indexBuilder.BuildAsync(ct),
    timeout: TimeSpan.FromSeconds(30) // this signal will be marked TimedOut if exceeded
);
Product 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 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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (21)

Showing the top 5 NuGet packages that depend on Veggerby.Ignition:

Package Downloads
Veggerby.Ignition.RabbitMq

RabbitMQ readiness signals for Veggerby.Ignition - verify broker connections, queues, and exchanges during application startup.

Veggerby.Ignition.MassTransit

MassTransit bus readiness signals for Veggerby.Ignition - verify message bus startup and connectivity during application initialization.

Veggerby.Ignition.Marten

Marten document store readiness signals for Veggerby.Ignition - verify Marten readiness during application startup.

Veggerby.Ignition.Postgres

PostgreSQL readiness signals for Veggerby.Ignition - verify database connections and schema during application startup.

Veggerby.Ignition.SqlServer

SQL Server readiness signals for Veggerby.Ignition - verify database connections and schema during application startup.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.6.0 441 2/2/2026
0.5.1-prerelease0023 423 2/2/2026
0.5.1-prerelease0022 445 1/26/2026
0.5.1-prerelease0021 425 1/22/2026
0.5.1-prerelease0020 438 1/22/2026
0.5.1-prerelease0019 434 1/21/2026
0.5.1-prerelease0018 387 1/21/2026
0.5.1-prerelease0017 379 1/20/2026
0.5.1-prerelease0016 362 1/20/2026
0.5.1-prerelease0014 358 1/20/2026
0.5.1-prerelease0013 359 1/20/2026
0.5.1-prerelease0011 350 1/19/2026
0.5.1-prerelease0009 336 1/19/2026
0.5.1-prerelease0008 346 1/17/2026
0.5.1-prerelease0007 301 1/16/2026
0.5.1-prerelease0006 297 1/16/2026
0.5.1-prerelease0004 302 1/16/2026
0.5.1-prerelease0003 290 1/15/2026
0.5.1-prerelease0002 296 1/15/2026
0.5.1-prerelease0001 297 1/15/2026
Loading failed