From a0c9f16aaee4e3622f4c688bd70b41344eea6390 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Wed, 30 Dec 2020 12:00:53 +0100 Subject: [PATCH] Add generic BackgroundWorker for running tasks asynchronously in the background --- .../Services/IBackgroundWorker.cs | 13 +++++++++ src/core/Elsa.Core/Elsa.Core.csproj | 1 + .../ElsaServiceCollectionExtensions.cs | 2 ++ .../HostedServices/StartBackgroundWorker.cs | 14 +++++++++ .../Elsa.Core/Services/BackgroundWorker.cs | 29 +++++++++++++++++++ 5 files changed, 59 insertions(+) create mode 100644 src/core/Elsa.Abstractions/Services/IBackgroundWorker.cs create mode 100644 src/core/Elsa.Core/HostedServices/StartBackgroundWorker.cs create mode 100644 src/core/Elsa.Core/Services/BackgroundWorker.cs diff --git a/src/core/Elsa.Abstractions/Services/IBackgroundWorker.cs b/src/core/Elsa.Abstractions/Services/IBackgroundWorker.cs new file mode 100644 index 000000000..d7a7ebb44 --- /dev/null +++ b/src/core/Elsa.Abstractions/Services/IBackgroundWorker.cs @@ -0,0 +1,13 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Elsa.Services +{ + public interface IBackgroundWorker + { + Task ScheduleTask(Func task, CancellationToken cancellationToken = default); + Task ScheduleTask(Action task, CancellationToken cancellationToken = default); + Task RunAsync(CancellationToken cancellationToken = default); + } +} \ No newline at end of file diff --git a/src/core/Elsa.Core/Elsa.Core.csproj b/src/core/Elsa.Core/Elsa.Core.csproj index da3351923..e23689e01 100644 --- a/src/core/Elsa.Core/Elsa.Core.csproj +++ b/src/core/Elsa.Core/Elsa.Core.csproj @@ -37,6 +37,7 @@ + diff --git a/src/core/Elsa.Core/Extensions/ElsaServiceCollectionExtensions.cs b/src/core/Elsa.Core/Extensions/ElsaServiceCollectionExtensions.cs index b61044d63..e0fc9987c 100644 --- a/src/core/Elsa.Core/Extensions/ElsaServiceCollectionExtensions.cs +++ b/src/core/Elsa.Core/Extensions/ElsaServiceCollectionExtensions.cs @@ -36,6 +36,7 @@ namespace Microsoft.Extensions.DependencyInjection this IServiceCollection services, Action? configure = default) { + services.AddHostedService(); services.AddStartupRunner(); var options = new ElsaOptions(services); @@ -95,6 +96,7 @@ namespace Microsoft.Extensions.DependencyInjection .AddSingleton() .AddSingleton() .AddSingleton() + .AddSingleton() .AddScoped() .AddScoped() .AddScoped() diff --git a/src/core/Elsa.Core/HostedServices/StartBackgroundWorker.cs b/src/core/Elsa.Core/HostedServices/StartBackgroundWorker.cs new file mode 100644 index 000000000..61578f263 --- /dev/null +++ b/src/core/Elsa.Core/HostedServices/StartBackgroundWorker.cs @@ -0,0 +1,14 @@ +using System.Threading; +using System.Threading.Tasks; +using Elsa.Services; +using Microsoft.Extensions.Hosting; + +namespace Elsa.HostedServices +{ + public class StartBackgroundWorker : BackgroundService + { + private readonly IBackgroundWorker _backgroundWorker; + public StartBackgroundWorker(IBackgroundWorker backgroundWorker) => _backgroundWorker = backgroundWorker; + protected override async Task ExecuteAsync(CancellationToken stoppingToken) => await _backgroundWorker.RunAsync(stoppingToken); + } +} \ No newline at end of file diff --git a/src/core/Elsa.Core/Services/BackgroundWorker.cs b/src/core/Elsa.Core/Services/BackgroundWorker.cs new file mode 100644 index 000000000..7fc54b296 --- /dev/null +++ b/src/core/Elsa.Core/Services/BackgroundWorker.cs @@ -0,0 +1,29 @@ +using System; +using System.Threading; +using System.Threading.Channels; +using System.Threading.Tasks; + +namespace Elsa.Services +{ + public class BackgroundWorker : IBackgroundWorker + { + private readonly Channel> _channel; + public BackgroundWorker() => _channel = Channel.CreateBounded>(10); + + public async Task ScheduleTask(Func task, CancellationToken cancellationToken) => await _channel.Writer.WriteAsync(task, cancellationToken); + + public async Task ScheduleTask(Action task, CancellationToken cancellationToken) => + await _channel.Writer.WriteAsync(() => + { + task(); + return new ValueTask(); + }, cancellationToken); + + public async Task RunAsync(CancellationToken cancellationToken) + { + while (await _channel.Reader.WaitToReadAsync(cancellationToken)) + while (_channel.Reader.TryRead(out var task)) + await task(); + } + } +} \ No newline at end of file