108 lines
3.2 KiB
C#
108 lines
3.2 KiB
C#
using System.Diagnostics;
|
|
using InServiceQue.Core.Models;
|
|
using InServiceQue.Core.Repositories;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Hosting;
|
|
|
|
namespace InServiceQue.Services;
|
|
|
|
public class QueueService<T> : BackgroundService, IQueueService<T>
|
|
where T: IQueueTask
|
|
{
|
|
private readonly ITaskRepository _repository;
|
|
private readonly IServiceProvider _serviceProvider;
|
|
|
|
public QueueService(ITaskRepository repository, IServiceProvider serviceProvider)
|
|
{
|
|
_repository = repository;
|
|
_serviceProvider = serviceProvider;
|
|
}
|
|
|
|
public void TryProcessTask()
|
|
{
|
|
using (var scope = _serviceProvider.CreateScope())
|
|
{
|
|
using var tx = _repository.StartTransaction();
|
|
var queueTask = _repository.GetNextTask(tx, typeof(T).Name);
|
|
if (queueTask == null)
|
|
{
|
|
_repository.RollbackTransaction(tx);
|
|
return;
|
|
}
|
|
|
|
var serviceHandler = scope.ServiceProvider.GetService(typeof(IQueueHandler<>).MakeGenericType(typeof(T)));
|
|
var handler = (IQueueHandler)serviceHandler;
|
|
|
|
try
|
|
{
|
|
Handle(queueTask, handler);
|
|
_repository.SaveTask(queueTask, tx);
|
|
_repository.CommitTransaction(tx);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
// ignored
|
|
}
|
|
}
|
|
}
|
|
|
|
public async Task TryProcessTaskAsync()
|
|
{
|
|
using (var scope = _serviceProvider.CreateScope())
|
|
{
|
|
using var tx = await _repository.StartTransactionAsync();
|
|
|
|
var taskType = typeof(T);
|
|
|
|
var queueTask = await _repository.GetNextTaskAsync(tx, taskType.Name);
|
|
if (queueTask == null)
|
|
{
|
|
await _repository.RollbackTransactionAsync(tx);
|
|
return;
|
|
}
|
|
|
|
var serviceHandler = scope.ServiceProvider.GetService(typeof(IQueueHandler<>).MakeGenericType(taskType));
|
|
var handler = (IQueueHandler)serviceHandler;
|
|
|
|
try
|
|
{
|
|
await HandleAsync(queueTask, handler);
|
|
await _repository.SaveTaskAsync(queueTask, tx);
|
|
await _repository.CommitTransactionAsync(tx);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
// ignored
|
|
}
|
|
}
|
|
}
|
|
|
|
internal void Handle(QueueTask queueTask, IQueueHandler handler)
|
|
{
|
|
queueTask.MarkAttempt();
|
|
var success = handler.Handle(queueTask.Payload ?? string.Empty);
|
|
if (success)
|
|
{
|
|
queueTask.SolveTask();
|
|
}
|
|
}
|
|
|
|
internal async Task HandleAsync(QueueTask queueTask, IQueueHandler handler)
|
|
{
|
|
queueTask.MarkAttempt();
|
|
var success = await handler.HandleAsync(queueTask.Payload ?? string.Empty);
|
|
if (success)
|
|
{
|
|
queueTask.SolveTask();
|
|
}
|
|
}
|
|
|
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
|
{
|
|
while (true)
|
|
{
|
|
await TryProcessTaskAsync();
|
|
await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
|
|
}
|
|
}
|
|
} |