dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.91k stars 4.63k forks source link

[API Proposal]: Add Option to Start IHostedService Instances According to Dependency Resolution Order #99846

Open lipchev opened 5 months ago

lipchev commented 5 months ago

Background and motivation

In .NET Core, the IHostedService interface is a powerful tool for running background tasks that should start when the application starts and stop when it shuts down. However, when multiple IHostedService instances have dependencies on each other, managing the startup order can become complex.

Currently, IHostedService instances are started in the order they are registered in the dependency injection container. This means that developers must carefully control the registration order to ensure that dependencies are resolved correctly. This can be error-prone and difficult to manage, especially in large applications with many interdependent services.

To simplify this process, I propose adding a new option to the HostOptions configuration: StartServicesAccordingToResolutionOrder. When this option is set to true, the framework would automatically start IHostedService instances in the order determined by the dependency resolution process, rather than the registration order. This would ensure that services are always started after their dependencies, regardless of the order in which they were registered.

This feature would complement the existing ServicesStartConcurrently option. If both ServicesStartConcurrently and StartServicesAccordingToResolutionOrder are set to true, the framework would start the IHostedService instances concurrently but still respect the order determined by the dependency resolution process. This means that even though the services are started concurrently, a service will not start until all its dependencies have finished starting. This provides developers with fine-grained control over the startup process, making it easier to manage complex dependencies between services even when they are started concurrently.

API Proposal

namespace Microsoft.Extensions.Hosting
{
    public class HostOptions
    {
        /// <summary>
        /// Indicates whether hosted services should be started according to their dependency resolution order.
        /// If true, the hosted services will be started in the order determined by the dependency resolution process.
        /// If false, the hosted services will be started in the order they were registered.
        /// The default value is false.
        /// </summary>
        public bool StartServicesAccordingToResolutionOrder { get; set; }
    }
}

API Usage

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureServices((hostContext, services) =>
        {
            services.AddHostedService<Worker>();
        })
        .UseDefaultServiceProvider((context, options) =>
        {
            options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
        })
        .ConfigureHostOptions(options =>
        {
            options.ServicesStartConcurrently = false; // Start services sequentially
            options.StartServicesAccordingToResolutionOrder = true; // Start services according to resolution order
        });
dotnet-policy-service[bot] commented 5 months ago

Tagging subscribers to this area: @dotnet/area-extensions-hosting See info in area-owners.md if you want to be subscribed.

steveharter commented 5 months ago

PTAL @davidfowl @halter73. Has this been discussed previously?