Worker service with parallel task queue, performance

Viewed 594

I'm trying to create an worker service that polls database every few seconds for emails. Emails are passed to a priorityQueue and from there sent via Rest API to external provider. I would like to also implement some kind of limit on number of threads used by queue.

So here is my ExecuteAsync from BackGroundService:

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {/*Poll email database*/
            var emails = await _emailRepository.GetEmailsToSend();

            foreach (var email in emails) /*Queue downloaded emails*/
                _queue.QueueEmail(email);

            await Task.Delay(_emailOptions.PollTime, stoppingToken);
        }
    }

And here is my BackgroundEmailQueue to which emails are given:

public class BackgroundEmailQueue : IBackgroundEmailQueue
{
    private readonly ILogger<BackgroundEmailQueue> logger;
    private readonly ConcurrentPriorityQueue<EmailToSend> queue;
    private readonly SemaphoreSlim signal;

    private event Action EmailQued;

    public BackgroundEmailQueue(ILogger<BackgroundEmailQueue> logger)
    {
        this.queue = new ConcurrentPriorityQueue<EmailToSend>();
        this.signal = new SemaphoreSlim(5, 5);
        this.EmailQued += OnEmailQued;
        
        this.logger = logger;
    }

    public void QueueEmail(EmailToSend email)
    {
        if (email == null)
            return;

        queue.Add(email);

        EmailQued.Invoke();
    }

    private async void OnEmailQued()
    {
        await signal.WaitAsync();

        var email = queue.Take();

        await Task.Run(async () => { .... /*sending email*/ } );

        signal.Release();
    }

}

This solution works as intended

My problem is:

Was using the event to fire new thread good solution?

Is there a better way to do this?

0 Answers
Related