Add result wait service

This commit is contained in:
2025-10-30 12:25:03 +09:00
parent 3bd7341ecc
commit e31a075f58
10 changed files with 152 additions and 32 deletions

View File

@ -27,24 +27,38 @@ namespace Hcs.WebApp.BackgroundServices
if (stoppingToken.IsCancellationRequested) return;
using var scope = scopeFactory.CreateScope();
try
var manager = managerFactory.CreateManager(campaign);
if (manager != null)
{
var manager = managerFactory.CreateManager(campaign);
await manager.StartAsync(scope);
try
{
await manager.StartAsync(scope);
managers.Add(manager);
managers.Add(manager);
}
catch (Exception e)
{
await manager.EndWithFailAsync(scope, e);
}
}
catch (Exception e)
else
{
var headquartersService = scope.ServiceProvider.GetRequiredService<HeadquartersService>();
await headquartersService.SetCampaignEndedWithFailAsync(campaign.Id, e.Message);
await headquartersService.SetCampaignEndedWithFailAsync(campaign.Id, "Не удалось найти подходящий менеджер кампании");
}
}
foreach (var manager in managers)
{
using var scope = scopeFactory.CreateScope();
await manager.CheckStateAsync(scope);
try
{
await manager.CheckStateAsync(scope);
}
catch (Exception e)
{
await manager.EndWithFailAsync(scope, e);
}
}
managers.RemoveAll(x => x.State == IManager.ManagerState.Ended);

View File

@ -3,8 +3,16 @@ using Hcs.WebApp.Services;
namespace Hcs.WebApp.BackgroundServices.CampaignManagers
{
public class ExportCommonRegistryElementsManager_15_7_0_1(OperationExecutionState operationExecutionState, Campaign campaign) : ManagerBase(operationExecutionState, campaign)
public class ExportCommonRegistryElementsManager_15_7_0_1(OperationExecutionState operationExecutionState, ResultWaitState resultWaitState, Campaign campaign) : ManagerBase(operationExecutionState, resultWaitState, campaign)
{
private enum Step
{
Start = 0,
Execution = 1,
Wait = 2,
End = 3
}
public override async Task StartAsync(IServiceScope scope)
{
if (campaign.StartedAt.HasValue)
@ -22,10 +30,14 @@ namespace Hcs.WebApp.BackgroundServices.CampaignManagers
try
{
await headquartersService.SetCampaignStartedAsync(context, campaign.Id);
await headquartersService.SetCampaignStepAsync(context, campaign.Id, 1);
campaign.Step = (int)Step.Execution;
await headquartersService.UpdateCampaignStepAsync(context, campaign);
var registryCount = await registryService.GetRegistryCountAsync(context, true);
operations = await headquartersService.InitiateOperationsAsync(context, registryCount, campaign.Id, Operation.OperationType.NsiCommon_ExportNsiItem_15_7_0_1);
await registryService.SetOperationsToRegistriesAsync(context, true, operations);
await transaction.CommitAsync();
}
catch
@ -50,13 +62,51 @@ namespace Hcs.WebApp.BackgroundServices.CampaignManagers
{
if (State == IManager.ManagerState.Started)
{
var headquartersService = scope.ServiceProvider.GetRequiredService<HeadquartersService>();
var hasActiveOperations = await headquartersService.HasActiveOperationsAsync(campaign.Id);
if (!hasActiveOperations)
switch ((Step)campaign.Step)
{
await headquartersService.SetCampaignEndedAsync(campaign.Id);
case Step.Execution:
if (!operationExecutionState.HasCampaignOperation(campaign.Id))
{
campaign.Step = (int)Step.Wait;
var headquartersService = scope.ServiceProvider.GetRequiredService<HeadquartersService>();
await headquartersService.UpdateCampaignStepAsync(campaign);
State = IManager.ManagerState.Ended;
var operations = await headquartersService.GetOperationsAsync(campaign.Id);
foreach (var operation in operations)
{
if (!string.IsNullOrEmpty(operation.MessageGuid))
{
resultWaitState.EnqueueOperation(operation);
}
}
}
break;
case Step.Wait:
if (!resultWaitState.HasCampaignOperation(campaign.Id))
{
var headquartersService = scope.ServiceProvider.GetRequiredService<HeadquartersService>();
using var context = headquartersService.GetNewContext();
using var transaction = await context.Database.BeginTransactionAsync();
try
{
campaign.Step = (int)Step.End;
await headquartersService.UpdateCampaignStepAsync(context, campaign);
await headquartersService.SetCampaignEndedAsync(campaign.Id);
await transaction.CommitAsync();
}
catch
{
transaction?.Rollback();
throw;
}
State = IManager.ManagerState.Ended;
}
break;
}
}
}

View File

@ -14,5 +14,7 @@
Task StartAsync(IServiceScope scope);
Task CheckStateAsync(IServiceScope scope);
Task EndWithFailAsync(IServiceScope scope, Exception e);
}
}

View File

@ -1,10 +1,12 @@
using Hcs.WebApp.Data.Hcs;
using Hcs.WebApp.Services;
namespace Hcs.WebApp.BackgroundServices.CampaignManagers
{
public abstract class ManagerBase(OperationExecutionState operationExecutionState, Campaign campaign) : IManager
public abstract class ManagerBase(OperationExecutionState operationExecutionState, ResultWaitState resultWaitState, Campaign campaign) : IManager
{
protected readonly OperationExecutionState operationExecutionState = operationExecutionState;
protected readonly ResultWaitState resultWaitState = resultWaitState;
protected readonly Campaign campaign = campaign;
public IManager.ManagerState State { get; protected set; } = IManager.ManagerState.Created;
@ -12,5 +14,13 @@ namespace Hcs.WebApp.BackgroundServices.CampaignManagers
public abstract Task StartAsync(IServiceScope scope);
public abstract Task CheckStateAsync(IServiceScope scope);
public async Task EndWithFailAsync(IServiceScope scope, Exception e)
{
State = IManager.ManagerState.Ended;
var headquartersService = scope.ServiceProvider.GetRequiredService<HeadquartersService>();
await headquartersService.SetCampaignEndedWithFailAsync(campaign.Id, e.Message);
}
}
}

View File

@ -2,19 +2,20 @@
namespace Hcs.WebApp.BackgroundServices.CampaignManagers
{
public class ManagerFactory(OperationExecutionState state)
public class ManagerFactory(OperationExecutionState operationExecutionState, ResultWaitState resultWaitState)
{
protected readonly OperationExecutionState state = state;
protected readonly OperationExecutionState operationExecutionState = operationExecutionState;
protected readonly ResultWaitState resultWaitState;
public IManager CreateManager(Campaign campaign)
public IManager? CreateManager(Campaign campaign)
{
switch (campaign.Type)
{
case Campaign.CampaignType.ExportCommonRegistryElements_15_7_0_1:
return new ExportCommonRegistryElementsManager_15_7_0_1(state, campaign);
return new ExportCommonRegistryElementsManager_15_7_0_1(operationExecutionState, resultWaitState, campaign);
}
throw new NotImplementedException();
return null;
}
}
}

View File

@ -16,5 +16,10 @@ namespace Hcs.WebApp.BackgroundServices
{
return operations.TryDequeue(out operation);
}
public bool HasCampaignOperation(int campaignId)
{
return operations.Any(x => x.CampaignId == campaignId);
}
}
}

View File

@ -0,0 +1,7 @@
namespace Hcs.WebApp.BackgroundServices
{
public class ResultWaitService
{
// TODO
}
}

View File

@ -0,0 +1,25 @@
using Hcs.WebApp.Data.Hcs;
using System.Collections.Concurrent;
namespace Hcs.WebApp.BackgroundServices
{
public class ResultWaitState
{
private readonly ConcurrentQueue<Operation> operations = new();
public void EnqueueOperation(Operation operation)
{
operations.Enqueue(operation);
}
public bool TryDequeueOperation(out Operation operation)
{
return operations.TryDequeue(out operation);
}
public bool HasCampaignOperation(int campaignId)
{
return operations.Any(x => x.CampaignId == campaignId);
}
}
}