Update campaign handling
This commit is contained in:
@ -8,16 +8,21 @@ namespace Hcs.WebApp.BackgroundServices
|
|||||||
ManagerFactory managerFactory,
|
ManagerFactory managerFactory,
|
||||||
IServiceScopeFactory scopeFactory) : BackgroundService
|
IServiceScopeFactory scopeFactory) : BackgroundService
|
||||||
{
|
{
|
||||||
|
private const int ITERATION_TIME = 1000;
|
||||||
private const int SLEEP_TIME = 30000;
|
private const int SLEEP_TIME = 30000;
|
||||||
|
|
||||||
private readonly CampaignManagementState campaignManagementState = campaignManagementState;
|
private readonly CampaignManagementState campaignManagementState = campaignManagementState;
|
||||||
private readonly ManagerFactory managerFactory = managerFactory;
|
private readonly ManagerFactory managerFactory = managerFactory;
|
||||||
private readonly IServiceScopeFactory scopeFactory = scopeFactory;
|
private readonly IServiceScopeFactory scopeFactory = scopeFactory;
|
||||||
|
private readonly List<IManager> managers = [];
|
||||||
|
|
||||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
{
|
{
|
||||||
await InitializeStateAsync();
|
await InitializeStateAsync();
|
||||||
|
|
||||||
|
using var scope = scopeFactory.CreateScope();
|
||||||
|
var headquartersService = scope.ServiceProvider.GetRequiredService<HeadquartersService>();
|
||||||
|
|
||||||
while (!stoppingToken.IsCancellationRequested)
|
while (!stoppingToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
while (campaignManagementState.TryDequeueCampaign(out var campaign))
|
while (campaignManagementState.TryDequeueCampaign(out var campaign))
|
||||||
@ -28,15 +33,25 @@ namespace Hcs.WebApp.BackgroundServices
|
|||||||
{
|
{
|
||||||
var manager = managerFactory.CreateManager(campaign);
|
var manager = managerFactory.CreateManager(campaign);
|
||||||
await manager.StartAsync(stoppingToken);
|
await manager.StartAsync(stoppingToken);
|
||||||
|
|
||||||
|
managers.Add(manager);
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
// TODO: Добавить таймауты
|
await headquartersService.SetCampaignEndedWithFail(campaign.Id, e.Message);
|
||||||
campaignManagementState.EnqueueCampaign(campaign);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Delay(SLEEP_TIME, stoppingToken);
|
managers.RemoveAll(x => x.State == IManager.ManagerState.Ended);
|
||||||
|
|
||||||
|
if (managers.Count > 0)
|
||||||
|
{
|
||||||
|
await Task.Delay(ITERATION_TIME, stoppingToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await Task.Delay(SLEEP_TIME, stoppingToken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,16 @@
|
|||||||
{
|
{
|
||||||
public interface IManager
|
public interface IManager
|
||||||
{
|
{
|
||||||
|
public enum ManagerState
|
||||||
|
{
|
||||||
|
Created,
|
||||||
|
Started,
|
||||||
|
Working,
|
||||||
|
Ended
|
||||||
|
}
|
||||||
|
|
||||||
|
public ManagerState State { get; }
|
||||||
|
|
||||||
Task StartAsync(CancellationToken cancellationToken);
|
Task StartAsync(CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,8 @@ namespace Hcs.WebApp.BackgroundServices.CampaignManagers
|
|||||||
protected readonly IServiceScopeFactory scopeFactory = scopeFactory;
|
protected readonly IServiceScopeFactory scopeFactory = scopeFactory;
|
||||||
protected readonly Campaign campaign = campaign;
|
protected readonly Campaign campaign = campaign;
|
||||||
|
|
||||||
|
public IManager.ManagerState State { get; } = IManager.ManagerState.Created;
|
||||||
|
|
||||||
public abstract Task StartAsync(CancellationToken cancellationToken);
|
public abstract Task StartAsync(CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,12 +38,12 @@ namespace Hcs.WebApp.BackgroundServices
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var executor = executorFactory.CreateExecutor(client, operation);
|
var executor = executorFactory.CreateExecutor(client, operation);
|
||||||
|
await headquartersService.SetOperationStarted(operation.Id);
|
||||||
messageGuid = await executor.ExecuteAsync(stoppingToken);
|
messageGuid = await executor.ExecuteAsync(stoppingToken);
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
// TODO: Добавить таймауты и макс количество попыток выполнения операции
|
await headquartersService.SetOperationEndedWithFail(operation.Id, e.Message);
|
||||||
state.EnqueueOperation(operation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(messageGuid))
|
if (!string.IsNullOrEmpty(messageGuid))
|
||||||
|
|||||||
@ -15,10 +15,16 @@ namespace Hcs.WebApp.Data.Hcs
|
|||||||
|
|
||||||
public string InitiatorId { get; set; }
|
public string InitiatorId { get; set; }
|
||||||
|
|
||||||
public DateTime StartedAt { get; set; }
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
|
public DateTime? StartedAt { get; set; }
|
||||||
|
|
||||||
public DateTime? EndedAt { get; set; }
|
public DateTime? EndedAt { get; set; }
|
||||||
|
|
||||||
|
public int Step { get; set; }
|
||||||
|
|
||||||
|
public string FailureReason { get; set; }
|
||||||
|
|
||||||
public virtual ICollection<Operation> Operations { get; set; } = [];
|
public virtual ICollection<Operation> Operations { get; set; } = [];
|
||||||
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
|
|||||||
@ -17,12 +17,16 @@ namespace Hcs.WebApp.Data.Hcs
|
|||||||
|
|
||||||
public OperationType Type { get; set; }
|
public OperationType Type { get; set; }
|
||||||
|
|
||||||
public DateTime StartedAt { get; set; }
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
|
public DateTime? StartedAt { get; set; }
|
||||||
|
|
||||||
public DateTime? EndedAt { get; set; }
|
public DateTime? EndedAt { get; set; }
|
||||||
|
|
||||||
public string? MessageGuid { get; set; }
|
public string? MessageGuid { get; set; }
|
||||||
|
|
||||||
|
public string FailureReason { get; set; }
|
||||||
|
|
||||||
public virtual ICollection<Registry> Registries { get; set; } = [];
|
public virtual ICollection<Registry> Registries { get; set; } = [];
|
||||||
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
|
|||||||
@ -36,7 +36,7 @@ namespace Hcs.WebApp.Services
|
|||||||
{
|
{
|
||||||
Type = type,
|
Type = type,
|
||||||
InitiatorId = initiatorId,
|
InitiatorId = initiatorId,
|
||||||
StartedAt = DateTime.UtcNow
|
CreatedAt = DateTime.UtcNow
|
||||||
};
|
};
|
||||||
await context.Campaigns.AddAsync(campaign);
|
await context.Campaigns.AddAsync(campaign);
|
||||||
await context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
@ -50,13 +50,51 @@ namespace Hcs.WebApp.Services
|
|||||||
{
|
{
|
||||||
CampaignId = campaignId,
|
CampaignId = campaignId,
|
||||||
Type = type,
|
Type = type,
|
||||||
StartedAt = DateTime.UtcNow
|
CreatedAt = DateTime.UtcNow
|
||||||
};
|
};
|
||||||
await context.Operations.AddAsync(operation);
|
await context.Operations.AddAsync(operation);
|
||||||
await context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task SetCampaignEndedWithFail(int campaignId, string failureReason)
|
||||||
|
{
|
||||||
|
using var context = factory.CreateDbContext();
|
||||||
|
var campaign = await context.Campaigns.FirstOrDefaultAsync(x => x.Id == campaignId);
|
||||||
|
if (campaign != null)
|
||||||
|
{
|
||||||
|
campaign.EndedAt = DateTime.UtcNow;
|
||||||
|
campaign.FailureReason = failureReason;
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SetOperationStarted(int operationId)
|
||||||
|
{
|
||||||
|
using var context = factory.CreateDbContext();
|
||||||
|
var operation = await context.Operations.FirstOrDefaultAsync(x => x.Id == operationId);
|
||||||
|
if (operation != null)
|
||||||
|
{
|
||||||
|
operation.StartedAt = DateTime.UtcNow;
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SetOperationEndedWithFail(int operationId, string failureReason)
|
||||||
|
{
|
||||||
|
using var context = factory.CreateDbContext();
|
||||||
|
var operation = await context.Operations.FirstOrDefaultAsync(x => x.Id == operationId);
|
||||||
|
if (operation != null)
|
||||||
|
{
|
||||||
|
operation.EndedAt = DateTime.UtcNow;
|
||||||
|
operation.FailureReason = failureReason;
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task SetOperationMessageGuidAsync(int operationId, string messageGuid)
|
public async Task SetOperationMessageGuidAsync(int operationId, string messageGuid)
|
||||||
{
|
{
|
||||||
using var context = factory.CreateDbContext();
|
using var context = factory.CreateDbContext();
|
||||||
|
|||||||
Reference in New Issue
Block a user