Codebelt

Codebelt.Bootstrapper.Worker

Conventional and minimal entry points for worker hosts that keep startup composition inside the bootstrapper model.

.NET 10.0 / .NET 9.0 MIT v5.1.1 6,949 downloads

Overview

Codebelt.Bootstrapper.Worker extends Codebelt.Bootstrapper with worker-specific entry points for applications that run through the generic host. It gives you a conventional Program plus Startup pairing through WorkerProgram<TStartup> and a lower-ceremony path through MinimalWorkerProgram.

The package focuses on host construction instead of the worker implementation itself. You register your own hosted services, while the bootstrapper applies its lifetime integration and worker-oriented startup composition before the host is built.

Key APIs

WorkerProgram<TStartup> is the conventional entry point for a worker service that uses a paired startup class. Its protected CreateHostBuilder(string[] args) creates the default host builder and applies UseBootstrapperLifetime(), UseBootstrapperEnvironmentDefaults<TStartup>(), and UseBootstrapperStartup<TStartup>() before you call Build().

WorkerStartup is the worker-specific startup base class. It specializes StartupRoot for hosted services by taking IConfiguration and IHostEnvironment in its constructor, then leaving service registration to the inherited ConfigureServices(IServiceCollection services) contract.

MinimalWorkerProgram is the entry point when you want direct access to HostApplicationBuilder instead of a dedicated startup type. Its protected CreateHostBuilder(string[] args) creates the builder, applies the bootstrapper lifetime, and adds the package's environment defaults before you continue configuring services.

Basic usage

using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Codebelt.Bootstrapper;
using Codebelt.Bootstrapper.Worker;
using Codebelt.Extensions.Xunit;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Xunit;

namespace MyProject.Tests;

public class WorkerProgramUsageTest : Test
{
    public WorkerProgramUsageTest(ITestOutputHelper output) : base(output) { }

    [Fact]
    public void ShouldRegisterStartupAndHostedService()
    {
        using var host = ExampleProgram.Create(Array.Empty<string>()).Build();
        var lifetime = host.Services.GetRequiredService<IHostLifetime>();
        var startupFactory = host.Services.GetRequiredService<IStartupFactory<ExampleStartup>>();
        var workers = host.Services.GetServices<IHostedService>().Select(worker => worker.GetType().Name).ToArray();

        TestOutput.WriteLine($"Lifetime: {lifetime.GetType().Name}");
        TestOutput.WriteLine($"Hosted services: {string.Join(", ", workers)}");

        Assert.IsType<BootstrapperLifetime>(lifetime);
        Assert.IsType<ExampleStartup>(startupFactory.Instance);
        Assert.Contains(nameof(ExampleWorker), workers);
    }

    private sealed class ExampleProgram : WorkerProgram<ExampleStartup>
    {
        public static IHostBuilder Create(string[] args) => CreateHostBuilder(args);
    }

    private sealed class ExampleStartup(IConfiguration configuration, IHostEnvironment environment) : WorkerStartup(configuration, environment)
    {
        public override void ConfigureServices(IServiceCollection services) => services.AddHostedService<ExampleWorker>();
    }

    private sealed class ExampleWorker : IHostedService
    {
        public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;
        public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
    }
}

Use this pattern when you want a worker host to stay conventional, with service registration centralized in a WorkerStartup type. It matters because WorkerProgram<TStartup> applies the bootstrapper lifetime and startup factory wiring before the host is built, so hosted services become part of the worker composition without extra host-builder plumbing.

Installation

dotnet add package Codebelt.Bootstrapper.Worker

Usage guidance

Choose this package when you want worker services to follow the same paired Program and Startup model as the rest of the Bootstrapper family, or when you want the minimal worker entry point without giving up the bootstrapper lifetime behavior. If you only need the lower-level host extensions such as UseBootstrapperLifetime() or startup factories without the worker-specific base types, use Codebelt.Bootstrapper directly.

Family packages