elsa-core/src/common/Elsa.Mediator/HostedServices/BackgroundEventPublisherHostedService.cs
Marko Lahma 492d6fcd35
Fixing some analyzer warnings (#5617)
* Fixing some analyzer warnings

* review feedback

---------

Co-authored-by: Sipke Schoorstra <sipkeschoorstra@outlook.com>
2024-07-05 15:14:28 +02:00

78 lines
2.8 KiB
C#

using System.Threading.Channels;
using Elsa.Mediator.Contracts;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace Elsa.Mediator.HostedServices;
/// <summary>
/// Continuously reads from a channel to which notifications can be sent, publishing each received notification.
/// </summary>
public class BackgroundEventPublisherHostedService : BackgroundService
{
private readonly int _workerCount;
private readonly INotificationsChannel _notificationsChannel;
private readonly IServiceScopeFactory _scopeFactory;
private readonly List<Channel<INotification>> _outputs;
private readonly ILogger _logger;
/// <inheritdoc />
public BackgroundEventPublisherHostedService(int workerCount, INotificationsChannel notificationsChannel, IServiceScopeFactory scopeFactory, ILogger<BackgroundEventPublisherHostedService> logger)
{
_workerCount = workerCount;
_notificationsChannel = notificationsChannel;
_scopeFactory = scopeFactory;
_logger = logger;
_outputs = new List<Channel<INotification>>(workerCount);
}
/// <inheritdoc />
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
{
var index = 0;
using var scope = _scopeFactory.CreateScope();
var notificationSender = scope.ServiceProvider.GetRequiredService<INotificationSender>();
for (var i = 0; i < _workerCount; i++)
{
var output = Channel.CreateUnbounded<INotification>();
_outputs.Add(output);
_ = ReadOutputAsync(output, notificationSender, cancellationToken);
}
var channelReader = _notificationsChannel.Reader;
await foreach (var notification in channelReader.ReadAllAsync(cancellationToken))
{
var output = _outputs[index];
await output.Writer.WriteAsync(notification, cancellationToken);
index = (index + 1) % _workerCount;
}
foreach (var output in _outputs)
{
output.Writer.Complete();
}
}
private async Task ReadOutputAsync(Channel<INotification> output, INotificationSender notificationSender, CancellationToken cancellationToken)
{
await foreach (var notification in output.Reader.ReadAllAsync(cancellationToken))
{
try
{
await notificationSender.SendAsync(notification, NotificationStrategy.Sequential, cancellationToken);
}
catch (OperationCanceledException e)
{
_logger.LogDebug(e, "An operation was cancelled while processing the queue");
}
catch (Exception e)
{
_logger.LogError(e, "An unhandled exception occured while processing the queue");
}
}
}
}