public BackgroundTask(IServiceProvider serviceProvider, ILogger <T> logger, IDistributedSemaphoreProvider distributedSemaphoreProvider) { this.serviceProvider = serviceProvider; this.logger = logger; this.distributedSemaphoreProvider = distributedSemaphoreProvider; using (var scope = serviceProvider.CreateScope()) { var configuration = serviceProvider.GetRequiredService <IConfiguration>().GetSection($"backgroundtask:{typeof(T).Name}"); var task = scope.ServiceProvider.GetRequiredService <T>(); var appName = Environment.GetEnvironmentVariable("APP_NAME") ?? Assembly.GetEntryAssembly()?.GetName().Name ?? string.Empty; schedule = CronExpression.Parse(configuration.GetValue("schedule", task.Schedule), CronFormat.IncludeSeconds); startupDelay = configuration.GetValue("initialDelay", task.InitialDelay); enabled = configuration.GetValue("enabled", true); var degreeOfParallelism = configuration.GetValue("degreeOfParallelism", task.DegreeOfParallelism); if (!string.IsNullOrEmpty(appName)) { appName += "-"; } semaphore = distributedSemaphoreProvider.CreateSemaphore($"{appName}backgroundtask:{typeof(T).Name}", degreeOfParallelism); logger.LogInformation("starting background task: initial delay {0}, schedule: {1}, parallelism: {2}", this.startupDelay, this.schedule.ToString(), task.DegreeOfParallelism); } }
/// <summary> /// Equivalent to calling <see cref="IDistributedSemaphoreProvider.CreateSemaphore(string, int)" /> and then /// <see cref="IDistributedSemaphore.AcquireAsync(TimeSpan?, CancellationToken)" />. /// </summary> public static ValueTask <IDistributedSynchronizationHandle> AcquireSemaphoreAsync(this IDistributedSemaphoreProvider provider, string name, int maxCount, TimeSpan?timeout = null, CancellationToken cancellationToken = default) => (provider ?? throw new ArgumentNullException(nameof(provider))).CreateSemaphore(name, maxCount).AcquireAsync(timeout, cancellationToken);