From fa485918cc6ef924eb2e06e05a00233229fc6045 Mon Sep 17 00:00:00 2001 From: "HOME-LAPTOP\\kshkulev" Date: Tue, 28 Oct 2025 15:03:54 +0900 Subject: [PATCH] Complete campaign flow --- .../CampaignManagementService.cs | 9 +- ...equiredRegistryElementsManager_15_7_0_1.cs | 43 ++++++++- .../CampaignManagers/IManager.cs | 5 +- .../CampaignManagers/ManagerBase.cs | 10 ++- .../OperationExecutionService.cs | 4 +- Hcs.WebApp/Services/HeadquartersService.cs | 89 ++++++++++++++----- Hcs.WebApp/Services/RegistryService.cs | 12 ++- 7 files changed, 132 insertions(+), 40 deletions(-) diff --git a/Hcs.WebApp/BackgroundServices/CampaignManagementService.cs b/Hcs.WebApp/BackgroundServices/CampaignManagementService.cs index 9060609..0c96b2f 100644 --- a/Hcs.WebApp/BackgroundServices/CampaignManagementService.cs +++ b/Hcs.WebApp/BackgroundServices/CampaignManagementService.cs @@ -30,17 +30,22 @@ namespace Hcs.WebApp.BackgroundServices try { var manager = managerFactory.CreateManager(scope, campaign); - await manager.StartAsync(stoppingToken); + await manager.StartAsync(); managers.Add(manager); } catch (Exception e) { var headquartersService = scope.ServiceProvider.GetRequiredService(); - await headquartersService.SetCampaignEndedWithFail(campaign.Id, e.Message); + await headquartersService.SetCampaignEndedWithFailAsync(campaign.Id, e.Message); } } + foreach (var manager in managers) + { + await manager.CheckStateAsync(); + } + managers.RemoveAll(x => x.State == IManager.ManagerState.Ended); if (managers.Count > 0) diff --git a/Hcs.WebApp/BackgroundServices/CampaignManagers/ExportRequiredRegistryElementsManager_15_7_0_1.cs b/Hcs.WebApp/BackgroundServices/CampaignManagers/ExportRequiredRegistryElementsManager_15_7_0_1.cs index f3e273e..54ded2a 100644 --- a/Hcs.WebApp/BackgroundServices/CampaignManagers/ExportRequiredRegistryElementsManager_15_7_0_1.cs +++ b/Hcs.WebApp/BackgroundServices/CampaignManagers/ExportRequiredRegistryElementsManager_15_7_0_1.cs @@ -3,22 +3,57 @@ using Hcs.WebApp.Services; namespace Hcs.WebApp.BackgroundServices.CampaignManagers { - public class ExportRequiredRegistryElementsManager_15_7_0_1(IServiceScope scope, OperationExecutionState state, Campaign campaign) : ManagerBase(scope, state, campaign) + public class ExportRequiredRegistryElementsManager_15_7_0_1(IServiceScope scope, OperationExecutionState operationExecutionState, Campaign campaign) : ManagerBase(scope, operationExecutionState, campaign) { - public override async Task StartAsync(CancellationToken cancellationToken) + public override async Task StartAsync() { + if (campaign.Step > 0) return; + var headquartersService = scope.ServiceProvider.GetRequiredService(); var registryService = scope.ServiceProvider.GetRequiredService(); using var context = headquartersService.GetNewContext(); - using var transaction = await context.Database.BeginTransactionAsync(cancellationToken); + using var transaction = await context.Database.BeginTransactionAsync(); + IEnumerable operations = null; try { - // TODO + await headquartersService.SetCampaignStartedAsync(context, campaign.Id); + await headquartersService.SetCampaignStepAsync(context, campaign.Id, 1); + var registryCount = await registryService.GetRegistryCountAsync(context); + operations = await headquartersService.InitiateOperationsAsync(context, registryCount, campaign.Id, Operation.OperationType.NsiCommon_ExportNsiItem_15_7_0_1); + await registryService.SetOperationsToRegistriesAsync(context, operations); + await transaction.CommitAsync(); } catch { + transaction?.Rollback(); + throw; } + + if (operations != null) + { + foreach (var operation in operations) + { + operationExecutionState.EnqueueOperation(operation); + } + } + + State = IManager.ManagerState.Started; + } + + public override async Task CheckStateAsync() + { + if (State == IManager.ManagerState.Started) + { + var headquartersService = scope.ServiceProvider.GetRequiredService(); + var hasActiveOperations = await headquartersService.HasActiveOperationsAsync(campaign.Id); + if (!hasActiveOperations) + { + State = IManager.ManagerState.Ended; + + await headquartersService.SetCampaignEndedAsync(campaign.Id); + } + } } } } diff --git a/Hcs.WebApp/BackgroundServices/CampaignManagers/IManager.cs b/Hcs.WebApp/BackgroundServices/CampaignManagers/IManager.cs index 0960ceb..e36f8e5 100644 --- a/Hcs.WebApp/BackgroundServices/CampaignManagers/IManager.cs +++ b/Hcs.WebApp/BackgroundServices/CampaignManagers/IManager.cs @@ -6,12 +6,13 @@ { Created, Started, - Working, Ended } public ManagerState State { get; } - Task StartAsync(CancellationToken cancellationToken); + Task StartAsync(); + + Task CheckStateAsync(); } } diff --git a/Hcs.WebApp/BackgroundServices/CampaignManagers/ManagerBase.cs b/Hcs.WebApp/BackgroundServices/CampaignManagers/ManagerBase.cs index e7efb4f..fdcc006 100644 --- a/Hcs.WebApp/BackgroundServices/CampaignManagers/ManagerBase.cs +++ b/Hcs.WebApp/BackgroundServices/CampaignManagers/ManagerBase.cs @@ -2,14 +2,16 @@ namespace Hcs.WebApp.BackgroundServices.CampaignManagers { - public abstract class ManagerBase(IServiceScope scope, OperationExecutionState state, Campaign campaign) : IManager + public abstract class ManagerBase(IServiceScope scope, OperationExecutionState operationExecutionState, Campaign campaign) : IManager { protected readonly IServiceScope scope = scope; - protected readonly OperationExecutionState state = state; + protected readonly OperationExecutionState operationExecutionState = operationExecutionState; protected readonly Campaign campaign = campaign; - public IManager.ManagerState State { get; } = IManager.ManagerState.Created; + public IManager.ManagerState State { get; protected set; } = IManager.ManagerState.Created; - public abstract Task StartAsync(CancellationToken cancellationToken); + public abstract Task StartAsync(); + + public abstract Task CheckStateAsync(); } } diff --git a/Hcs.WebApp/BackgroundServices/OperationExecutionService.cs b/Hcs.WebApp/BackgroundServices/OperationExecutionService.cs index 34cbf0f..b1f1768 100644 --- a/Hcs.WebApp/BackgroundServices/OperationExecutionService.cs +++ b/Hcs.WebApp/BackgroundServices/OperationExecutionService.cs @@ -37,12 +37,12 @@ namespace Hcs.WebApp.BackgroundServices try { var executor = executorFactory.CreateExecutor(scope, client, operation); - await headquartersService.SetOperationStarted(operation.Id); + await headquartersService.SetOperationStartedAsync(operation.Id); messageGuid = await executor.ExecuteAsync(stoppingToken); } catch (Exception e) { - await headquartersService.SetOperationEndedWithFail(operation.Id, e.Message); + await headquartersService.SetOperationEndedWithFailAsync(operation.Id, e.Message); } if (!string.IsNullOrEmpty(messageGuid)) diff --git a/Hcs.WebApp/Services/HeadquartersService.cs b/Hcs.WebApp/Services/HeadquartersService.cs index 9f30d5f..56a35ba 100644 --- a/Hcs.WebApp/Services/HeadquartersService.cs +++ b/Hcs.WebApp/Services/HeadquartersService.cs @@ -11,6 +11,12 @@ namespace Hcs.WebApp.Services return await context.Campaigns.AnyAsync(x => x.Type == type && !x.EndedAt.HasValue); } + public async Task HasActiveOperationsAsync(int campaignId) + { + using var context = GetNewContext(); + return await context.Operations.CountAsync(x => x.CampaignId == campaignId && !x.EndedAt.HasValue) > 0; + } + public async Task> GetInitiatedCampaignAsync() { using var context = GetNewContext(); @@ -41,21 +47,59 @@ namespace Hcs.WebApp.Services return campaign; } - public async Task InitiateOperationAsync(int campaignId, Operation.OperationType type) + public async Task> InitiateOperationsAsync(HcsDbContext context, int count, int campaignId, Operation.OperationType type) { - using var context = GetNewContext(); - var operation = new Operation() + var operations = new List(); + for (var i = 0; i < count; i++) { - CampaignId = campaignId, - Type = type, - CreatedAt = DateTime.UtcNow - }; - await context.Operations.AddAsync(operation); + operations.Add(new Operation() + { + CampaignId = campaignId, + Type = type, + CreatedAt = DateTime.UtcNow + }); + } + await context.Operations.AddRangeAsync(operations); await context.SaveChangesAsync(); - return operation; + return operations; } - public async Task SetCampaignEndedWithFail(int campaignId, string failureReason) + public async Task SetCampaignStartedAsync(HcsDbContext context, int campaignId) + { + var campaign = await context.Campaigns.FirstOrDefaultAsync(x => x.Id == campaignId); + if (campaign != null) + { + campaign.StartedAt = DateTime.UtcNow; + + await context.SaveChangesAsync(); + } + } + + public async Task SetOperationStartedAsync(int operationId) + { + using var context = GetNewContext(); + var operation = await context.Operations.FirstOrDefaultAsync(x => x.Id == operationId); + if (operation != null) + { + operation.StartedAt = DateTime.UtcNow; + + await context.SaveChangesAsync(); + } + } + + public async Task SetCampaignEndedAsync(int campaignId) + { + using var context = GetNewContext(); + var campaign = await context.Campaigns.FirstOrDefaultAsync(x => x.Id == campaignId); + if (campaign != null) + { + campaign.EndedAt = DateTime.UtcNow; + + await context.SaveChangesAsync(); + } + } + + public async Task SetCampaignEndedWithFailAsync(int campaignId, string failureReason) { using var context = GetNewContext(); var campaign = await context.Campaigns.FirstOrDefaultAsync(x => x.Id == campaignId); @@ -68,19 +112,7 @@ namespace Hcs.WebApp.Services } } - public async Task SetOperationStarted(int operationId) - { - using var context = GetNewContext(); - 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) + public async Task SetOperationEndedWithFailAsync(int operationId, string failureReason) { using var context = GetNewContext(); var operation = await context.Operations.FirstOrDefaultAsync(x => x.Id == operationId); @@ -104,5 +136,16 @@ namespace Hcs.WebApp.Services await context.SaveChangesAsync(); } } + + public async Task SetCampaignStepAsync(HcsDbContext context, int campaignId, int step) + { + var campaign = await context.Campaigns.FirstOrDefaultAsync(x => x.Id == campaignId); + if (campaign != null) + { + campaign.Step = step; + + await context.SaveChangesAsync(); + } + } } } diff --git a/Hcs.WebApp/Services/RegistryService.cs b/Hcs.WebApp/Services/RegistryService.cs index ac14101..aa877a1 100644 --- a/Hcs.WebApp/Services/RegistryService.cs +++ b/Hcs.WebApp/Services/RegistryService.cs @@ -5,6 +5,11 @@ namespace Hcs.WebApp.Services { public class RegistryService(IDbContextFactory factory) : HcsServiceBase(factory) { + public async Task GetRegistryCountAsync(HcsDbContext context) + { + return await context.Registries.CountAsync(); + } + public async Task> GetAllRegistriesAsync(bool isCommon) { using var context = GetNewContext(); @@ -19,7 +24,7 @@ namespace Hcs.WebApp.Services return await context.Registries.SingleAsync(x => x.LastSyncOperationId == operationId); } - public async Task> GetRegistriesByOperationId(int operationId) + public async Task> GetRegistriesByOperationIdAsync(int operationId) { using var context = GetNewContext(); return await (from registry in context.Registries @@ -27,9 +32,10 @@ namespace Hcs.WebApp.Services select registry).ToListAsync(); } - public async Task SetOperationIdToAllRegistries(HcsDbContext context, int operationId) + public async Task SetOperationsToRegistriesAsync(HcsDbContext context, IEnumerable operations) { - await context.Registries.ForEachAsync(x => x.LastSyncOperationId = operationId); + var queue = new Queue(operations); + await context.Registries.ForEachAsync(x => x.LastSyncOperationId = queue.Dequeue().Id); await context.SaveChangesAsync(); } }