Отправка запланированных писем с помощью веб-API с помощью фоновых задач - PullRequest
0 голосов
/ 10 ноября 2018

Я слишком много исследовал о способах отправки запланированных писем с помощью основного веб-API .NET с использованием фоновых задач. Я знаю, что лучше выполнять фоновые задачи в службе Windows, которая работает отдельно с доменом приложения.

Но мое требование от веб-клиента. У меня будет таблица, в которой каждая строка является рекламным событием для клиента, я могу выбрать активировать, приостановить, остановить для каждого из них, затем он вызовет API и отсюда.

Я должен реализовать каждую фоновую задачу для каждой из них, которая может работать синхронно. Я должен сделать это через Web API, потому что у конечных пользователей нет места для размещения службы.

Фактическое решение :

Через день я пришел к решению, которое использует IHostedService с BlockingCollection для управления фоновыми задачами во время выполнения, как показано ниже:

Код для фоновой задачи с использованием IHostedService:

namespace SimCard.API.Worker
{
    internal class TimedHostedService : IHostedService, IDisposable
    {
        private CancellationTokenSource _tokenSource;
        private readonly ILogger _logger;
        private Timer _timer;
        private readonly TasksToRun tasks;
        private readonly IEmailService emailService;

        public TimedHostedService(ILogger<TimedHostedService> logger, TasksToRun tasks, IEmailService emailService)
        {
        this.emailService = emailService;
        this.tasks = tasks;
        _logger = logger;
        }

        public Task StartAsync(CancellationToken cancellationToken)
       {
        tasks.Dequeue();
        _logger.LogInformation("Timed Background Service is starting.");

        _timer = new Timer(DoWork, null, TimeSpan.Zero,
            TimeSpan.FromSeconds(5));

        return Task.CompletedTask;
       }

       private void DoWork(object state)
       {
        emailService.SendEmail("ptkhuong96@gmail.com", "Test", "OK, Done now");
        _logger.LogInformation("Mail sent!");
       }

        public Task StopAsync(CancellationToken cancellationToken)
        {
        _logger.LogInformation("Timed Background Service is stopping.");

        _timer?.Change(Timeout.Infinite, 0);

        return Task.CompletedTask;
        }

       public void Dispose()
       {
        _timer?.Dispose();
       }
   }

}

Вот код для BlockingCollection:

namespace SimCard.API.Worker
{
    public class TasksToRun : ITasksToRun
    {
       private readonly BlockingCollection<int> _tasks;

       public TasksToRun() => _tasks = new BlockingCollection<int>();

       public void Enqueue(int settings) => _tasks.Add(settings);

       public void Dequeue() => _tasks.Take();
   }
}

И код в контроллере с вызовом из веб-клиента:

    [HttpPost("/api/worker/start")]

    public IActionResult Run()
    {
        tasks.Enqueue(15);
        return Ok();
    }

Код для Startup.cs:

    services.AddHostedService<TimedHostedService>();
    services.AddSingleton<TasksToRun, TasksToRun>();

Проблема:

  1. После нажатия активной кнопки для первого события => будет вызван контроллер и будет запущен один экземпляр этой фоновой задачи. Как приостановить эту задачу и возобновить ее?
  2. Если первая проблема решена, как я могу создать каждую фоновую задачу для каждого события в таблице, подумайте о том, могу ли я создать в будущем все больше и больше событий, как одно событие может быть активировано, остановлено, приостановлено, возобновлено без влияния на другого?

Я действительно застрял с этим требованием и не знаю, как действовать дальше. Если у вас есть другой подход, который может адаптировать мой случай, вы также можете порекомендовать меня.

Большое спасибо за вашу поддержку.

...