Change events args

This commit is contained in:
2025-11-05 18:49:58 +09:00
parent e58221c430
commit 1d58bf8439
10 changed files with 99 additions and 66 deletions

View File

@ -40,14 +40,17 @@ namespace Hcs.WebApp.BackgroundServices
manager.OnCampaignStarted += OnCampaignStarted; manager.OnCampaignStarted += OnCampaignStarted;
manager.OnCampaignProgressStep += OnCampaignProgressStep; manager.OnCampaignProgressStep += OnCampaignProgressStep;
manager.OnCampaignEnded += OnCampaignEnded;
} }
else else
{ {
using var scope = scopeFactory.CreateScope(); using var scope = scopeFactory.CreateScope();
var headquartersService = scope.ServiceProvider.GetRequiredService<HeadquartersService>(); var headquartersService = scope.ServiceProvider.GetRequiredService<HeadquartersService>();
await headquartersService.SetCampaignEndedWithFailAsync(campaign.Id, "Не удалось найти подходящий менеджер кампании"); var endedAt = DateTime.UtcNow;
var failureReason = "Не удалось найти подходящий менеджер кампании";
await headquartersService.SetCampaignEndedWithFailAsync(campaign.Id, endedAt, failureReason);
campaignManagementState.InvokeOnCampaignEnded(campaign); campaignManagementState.InvokeOnCampaignEnded(campaign.Id, campaign.Type, endedAt, failureReason);
} }
} }
@ -64,10 +67,9 @@ namespace Hcs.WebApp.BackgroundServices
if (manager.State == IManager.ManagerState.Ended) if (manager.State == IManager.ManagerState.Ended)
{ {
campaignManagementState.InvokeOnCampaignEnded(manager.Campaign);
manager.OnCampaignStarted -= OnCampaignStarted; manager.OnCampaignStarted -= OnCampaignStarted;
manager.OnCampaignProgressStep -= OnCampaignProgressStep; manager.OnCampaignProgressStep -= OnCampaignProgressStep;
manager.OnCampaignEnded -= OnCampaignEnded;
} }
} }
@ -104,14 +106,19 @@ namespace Hcs.WebApp.BackgroundServices
} }
} }
private void OnCampaignStarted(Campaign campaign) private void OnCampaignStarted(int campaignId, DateTime startedAt)
{ {
campaignManagementState.InvokeOnCampaignStarted(campaign); campaignManagementState.InvokeOnCampaignStarted(campaignId, startedAt);
} }
private void OnCampaignProgressStep(Campaign campaign) private void OnCampaignProgressStep(int campaignId, int step, int progress)
{ {
campaignManagementState.InvokeOnCampaignProgressStep(campaign); campaignManagementState.InvokeOnCampaignProgressStep(campaignId, step, progress);
}
private void OnCampaignEnded(int campaignId, Campaign.CampaignType type, DateTime endedAt, string failureReason)
{
campaignManagementState.InvokeOnCampaignEnded(campaignId, type, endedAt, failureReason);
} }
} }
} }

View File

@ -5,12 +5,16 @@ namespace Hcs.WebApp.BackgroundServices
{ {
public class CampaignManagementState public class CampaignManagementState
{ {
public delegate void CampaignStarted(int campaignId, DateTime startedAt);
public delegate void CampaignProgressStep(int campaignId, int step, int progress);
public delegate void CampaignEnded(int campaignId, Campaign.CampaignType type, DateTime endedAt, string failureReason);
private readonly ConcurrentQueue<Campaign> campaigns = new(); private readonly ConcurrentQueue<Campaign> campaigns = new();
public event Action<Campaign> OnCampaignCreated; public event Action<Campaign> OnCampaignCreated;
public event Action<Campaign> OnCampaignStarted; public event CampaignStarted OnCampaignStarted;
public event Action<Campaign> OnCampaignProgressStep; public event CampaignProgressStep OnCampaignProgressStep;
public event Action<Campaign> OnCampaignEnded; public event CampaignEnded OnCampaignEnded;
public void EnqueueCampaign(Campaign campaign) public void EnqueueCampaign(Campaign campaign)
{ {
@ -24,29 +28,29 @@ namespace Hcs.WebApp.BackgroundServices
return campaigns.TryDequeue(out campaign); return campaigns.TryDequeue(out campaign);
} }
public void InvokeOnCampaignStarted(Campaign campaign) public void InvokeOnCampaignStarted(int campaignId, DateTime startedAt)
{ {
try try
{ {
OnCampaignStarted?.Invoke(campaign); OnCampaignStarted?.Invoke(campaignId, startedAt);
} }
catch { } catch { }
} }
public void InvokeOnCampaignProgressStep(Campaign campaign) public void InvokeOnCampaignProgressStep(int campaignId, int step, int progress)
{ {
try try
{ {
OnCampaignProgressStep?.Invoke(campaign); OnCampaignProgressStep?.Invoke(campaignId, step, progress);
} }
catch { } catch { }
} }
public void InvokeOnCampaignEnded(Campaign campaign) public void InvokeOnCampaignEnded(int campaignId, Campaign.CampaignType type, DateTime endedAt, string failureReason)
{ {
try try
{ {
OnCampaignEnded?.Invoke(campaign); OnCampaignEnded?.Invoke(campaignId, type, endedAt, failureReason);
} }
catch { } catch { }
} }

View File

@ -44,6 +44,7 @@ namespace Hcs.WebApp.BackgroundServices.CampaignManagers
private async Task DoStartStepAsync() private async Task DoStartStepAsync()
{ {
DateTime startedAt = default;
IEnumerable<Operation>? operations = null; IEnumerable<Operation>? operations = null;
using var context = HeadquartersService.GetNewContext(); using var context = HeadquartersService.GetNewContext();
@ -53,7 +54,8 @@ namespace Hcs.WebApp.BackgroundServices.CampaignManagers
using var transaction = await context.Database.BeginTransactionAsync(); using var transaction = await context.Database.BeginTransactionAsync();
try try
{ {
await HeadquartersService.SetCampaignStartedAsync(context, campaign.Id); startedAt = DateTime.UtcNow;
await HeadquartersService.SetCampaignStartedAsync(context, campaign.Id, startedAt);
await ProgressStepAsync(context, (int)Step.ExecutionWait); await ProgressStepAsync(context, (int)Step.ExecutionWait);
@ -80,6 +82,8 @@ namespace Hcs.WebApp.BackgroundServices.CampaignManagers
} }
State = IManager.ManagerState.Started; State = IManager.ManagerState.Started;
InvokeOnCampaignStarted(startedAt);
} }
private async Task DoExecutionWaitStepAsync() private async Task DoExecutionWaitStepAsync()
@ -102,6 +106,8 @@ namespace Hcs.WebApp.BackgroundServices.CampaignManagers
{ {
if (resultWaitState.HasCampaignOperation(campaign.Id)) return; if (resultWaitState.HasCampaignOperation(campaign.Id)) return;
DateTime endedAt = default;
using var context = HeadquartersService.GetNewContext(); using var context = HeadquartersService.GetNewContext();
var executionStrategy = context.Database.CreateExecutionStrategy(); var executionStrategy = context.Database.CreateExecutionStrategy();
await executionStrategy.ExecuteAsync(async () => await executionStrategy.ExecuteAsync(async () =>
@ -111,7 +117,8 @@ namespace Hcs.WebApp.BackgroundServices.CampaignManagers
{ {
await ProgressStepAsync(context, (int)Step.End); await ProgressStepAsync(context, (int)Step.End);
await HeadquartersService.SetCampaignEndedAsync(context, campaign.Id); endedAt = DateTime.UtcNow;
await HeadquartersService.SetCampaignEndedAsync(context, campaign.Id, endedAt);
await transaction.CommitAsync(); await transaction.CommitAsync();
} }
@ -124,6 +131,8 @@ namespace Hcs.WebApp.BackgroundServices.CampaignManagers
}); });
State = IManager.ManagerState.Ended; State = IManager.ManagerState.Ended;
InvokeOnCampaignEnded(endedAt, string.Empty);
} }
} }
} }

View File

@ -44,6 +44,7 @@ namespace Hcs.WebApp.BackgroundServices.CampaignManagers
private async Task DoStartStepAsync() private async Task DoStartStepAsync()
{ {
DateTime startedAt = default;
IEnumerable<Operation>? operations = null; IEnumerable<Operation>? operations = null;
using var context = HeadquartersService.GetNewContext(); using var context = HeadquartersService.GetNewContext();
@ -53,7 +54,8 @@ namespace Hcs.WebApp.BackgroundServices.CampaignManagers
using var transaction = await context.Database.BeginTransactionAsync(); using var transaction = await context.Database.BeginTransactionAsync();
try try
{ {
await HeadquartersService.SetCampaignStartedAsync(context, campaign.Id); startedAt = DateTime.UtcNow;
await HeadquartersService.SetCampaignStartedAsync(context, campaign.Id, startedAt);
await ProgressStepAsync(context, (int)Step.ExecutionWait); await ProgressStepAsync(context, (int)Step.ExecutionWait);
@ -80,6 +82,8 @@ namespace Hcs.WebApp.BackgroundServices.CampaignManagers
} }
State = IManager.ManagerState.Started; State = IManager.ManagerState.Started;
InvokeOnCampaignStarted(startedAt);
} }
private async Task DoExecutionWaitStepAsync() private async Task DoExecutionWaitStepAsync()
@ -102,6 +106,8 @@ namespace Hcs.WebApp.BackgroundServices.CampaignManagers
{ {
if (resultWaitState.HasCampaignOperation(campaign.Id)) return; if (resultWaitState.HasCampaignOperation(campaign.Id)) return;
DateTime endedAt = default;
using var context = HeadquartersService.GetNewContext(); using var context = HeadquartersService.GetNewContext();
var executionStrategy = context.Database.CreateExecutionStrategy(); var executionStrategy = context.Database.CreateExecutionStrategy();
await executionStrategy.ExecuteAsync(async () => await executionStrategy.ExecuteAsync(async () =>
@ -111,7 +117,8 @@ namespace Hcs.WebApp.BackgroundServices.CampaignManagers
{ {
await ProgressStepAsync(context, (int)Step.End); await ProgressStepAsync(context, (int)Step.End);
await HeadquartersService.SetCampaignEndedAsync(context, campaign.Id); endedAt = DateTime.UtcNow;
await HeadquartersService.SetCampaignEndedAsync(context, campaign.Id, endedAt);
await transaction.CommitAsync(); await transaction.CommitAsync();
} }
@ -124,6 +131,8 @@ namespace Hcs.WebApp.BackgroundServices.CampaignManagers
}); });
State = IManager.ManagerState.Ended; State = IManager.ManagerState.Ended;
InvokeOnCampaignEnded(endedAt, string.Empty);
} }
} }
} }

View File

@ -4,6 +4,10 @@ namespace Hcs.WebApp.BackgroundServices.CampaignManagers
{ {
public interface IManager public interface IManager
{ {
public delegate void CampaignStarted(int campaignId, DateTime startedAt);
public delegate void CampaignProgressStep(int campaignId, int step, int progress);
public delegate void CampaignEnded(int campaignId, Campaign.CampaignType type, DateTime endedAt, string failureReason);
public enum ManagerState public enum ManagerState
{ {
Created, Created,
@ -15,8 +19,9 @@ namespace Hcs.WebApp.BackgroundServices.CampaignManagers
public ManagerState State { get; } public ManagerState State { get; }
event Action<Campaign> OnCampaignStarted; event CampaignStarted OnCampaignStarted;
event Action<Campaign> OnCampaignProgressStep; event CampaignProgressStep OnCampaignProgressStep;
event CampaignEnded OnCampaignEnded;
Task ProcessAsync(); Task ProcessAsync();

View File

@ -15,42 +15,36 @@ namespace Hcs.WebApp.BackgroundServices.CampaignManagers
protected readonly ResultWaitState resultWaitState = resultWaitState; protected readonly ResultWaitState resultWaitState = resultWaitState;
protected readonly Campaign campaign = campaign; protected readonly Campaign campaign = campaign;
private IManager.ManagerState state;
private HeadquartersService? headquartersService; private HeadquartersService? headquartersService;
public Campaign Campaign => campaign; public Campaign Campaign => campaign;
public IManager.ManagerState State public IManager.ManagerState State { get; protected set; }
{
get => state;
set
{
if (state != value)
{
state = value;
if (state == IManager.ManagerState.Started)
{
OnCampaignStarted?.Invoke(campaign);
}
}
}
}
protected HeadquartersService HeadquartersService => headquartersService ??= scope.ServiceProvider.GetRequiredService<HeadquartersService>(); protected HeadquartersService HeadquartersService => headquartersService ??= scope.ServiceProvider.GetRequiredService<HeadquartersService>();
protected abstract int StepCount { get; } protected abstract int StepCount { get; }
public event Action<Campaign> OnCampaignStarted; public event IManager.CampaignStarted OnCampaignStarted;
public event Action<Campaign>? OnCampaignProgressStep; public event IManager.CampaignProgressStep OnCampaignProgressStep;
public event IManager.CampaignEnded OnCampaignEnded;
public abstract Task ProcessAsync(); public abstract Task ProcessAsync();
public async Task EndWithFailAsync(Exception e) public async Task EndWithFailAsync(Exception e)
{ {
await HeadquartersService.SetCampaignEndedWithFailAsync(campaign.Id, e.CombineMessages()); var endedAt = DateTime.UtcNow;
var failureReason = e.CombineMessages();
await HeadquartersService.SetCampaignEndedWithFailAsync(campaign.Id, endedAt, failureReason);
State = IManager.ManagerState.Ended; State = IManager.ManagerState.Ended;
InvokeOnCampaignEnded(endedAt, failureReason);
}
protected void InvokeOnCampaignStarted(DateTime startedAt)
{
OnCampaignStarted?.Invoke(campaign.Id, startedAt);
} }
protected async Task ProgressStepAsync(int step) protected async Task ProgressStepAsync(int step)
@ -59,13 +53,18 @@ namespace Hcs.WebApp.BackgroundServices.CampaignManagers
await ProgressStepAsync(context, step); await ProgressStepAsync(context, step);
} }
protected void InvokeOnCampaignEnded(DateTime endedAt, string failureReason)
{
OnCampaignEnded?.Invoke(campaign.Id, campaign.Type, endedAt, failureReason);
}
protected async Task ProgressStepAsync(HcsDbContext context, int step) protected async Task ProgressStepAsync(HcsDbContext context, int step)
{ {
campaign.Step = step; campaign.Step = step;
campaign.Progress = Convert.ToInt32(((step + 1) / (float)StepCount * 100)); campaign.Progress = Convert.ToInt32(((step + 1) / (float)StepCount * 100));
await HeadquartersService.UpdateCampaignStepAndProgressAsync(context, campaign); await HeadquartersService.UpdateCampaignStepAndProgressAsync(context, campaign);
OnCampaignProgressStep?.Invoke(campaign); OnCampaignProgressStep?.Invoke(campaign.Id, campaign.Step, campaign.Progress);
} }
} }
} }

View File

@ -137,38 +137,38 @@
Task.Run(RefreshCampaigns); Task.Run(RefreshCampaigns);
} }
void OnCampaignStarted(Campaign campaign) void OnCampaignStarted(int campaignId, DateTime startedAt)
{ {
InvokeAsync(() => InvokeAsync(() =>
{ {
var targetCampaign = campaigns?.FirstOrDefault(x => x.Id == campaign.Id); var targetCampaign = campaigns?.FirstOrDefault(x => x.Id == campaignId);
if (targetCampaign != null) if (targetCampaign != null)
{ {
targetCampaign.StartedAt = campaign.StartedAt; targetCampaign.StartedAt = startedAt;
campaignsDataGrid.Reload(); campaignsDataGrid.Reload();
} }
if (expandedCampaign != null && expandedCampaign.Id == campaign.Id) if (expandedCampaign != null && expandedCampaign.Id == campaignId)
{ {
campaignsDataGrid.CollapseAll(); campaignsDataGrid.CollapseAll();
} }
}); });
} }
void OnCampaignProgressStep(Campaign campaign) void OnCampaignProgressStep(int campaignId, int step, int progress)
{ {
InvokeAsync(() => InvokeAsync(() =>
{ {
var targetCampaign = campaigns?.FirstOrDefault(x => x.Id == campaign.Id); var targetCampaign = campaigns?.FirstOrDefault(x => x.Id == campaignId);
if (targetCampaign != null) if (targetCampaign != null)
{ {
targetCampaign.Step = campaign.Step; targetCampaign.Step = step;
targetCampaign.Progress = campaign.Progress; targetCampaign.Progress = progress;
campaignsDataGrid.Reload(); campaignsDataGrid.Reload();
if (expandedCampaign != null && expandedCampaign.Id == campaign.Id) if (expandedCampaign != null && expandedCampaign.Id == campaignId)
{ {
campaignsDataGrid.CollapseAll(); campaignsDataGrid.CollapseAll();
} }
@ -176,7 +176,7 @@
}); });
} }
void OnCampaignEnded(Campaign campaign) void OnCampaignEnded(int campaignId, Campaign.CampaignType type, DateTime endedAt, string failureReason)
{ {
Task.Run(RefreshCampaigns); Task.Run(RefreshCampaigns);
} }

View File

@ -184,9 +184,9 @@
} }
} }
void OnCampaignEnded(Campaign campaign) void OnCampaignEnded(int campaignId, Campaign.CampaignType type, DateTime endedAt, string failureReason)
{ {
if (campaign.Type == Campaign.CampaignType.ExportCommonRegistryElements_15_7_0_1) if (type == Campaign.CampaignType.ExportCommonRegistryElements_15_7_0_1)
{ {
Task.Run(RefreshRegistries); Task.Run(RefreshRegistries);
} }

View File

@ -184,9 +184,9 @@
} }
} }
void OnCampaignEnded(Campaign campaign) void OnCampaignEnded(int campaignId, Campaign.CampaignType type, DateTime endedAt, string failureReason)
{ {
if (campaign.Type == Campaign.CampaignType.ExportPrivateRegistryElements_15_7_0_1) if (type == Campaign.CampaignType.ExportPrivateRegistryElements_15_7_0_1)
{ {
Task.Run(RefreshRegistries); Task.Run(RefreshRegistries);
} }

View File

@ -80,12 +80,12 @@ namespace Hcs.WebApp.Services
return operations; return operations;
} }
public async Task SetCampaignStartedAsync(HcsDbContext context, int campaignId) public async Task SetCampaignStartedAsync(HcsDbContext context, int campaignId, DateTime startedAt)
{ {
var campaign = await context.Campaigns.FirstOrDefaultAsync(x => x.Id == campaignId); var campaign = await context.Campaigns.FirstOrDefaultAsync(x => x.Id == campaignId);
if (campaign != null) if (campaign != null)
{ {
campaign.StartedAt = DateTime.UtcNow; campaign.StartedAt = startedAt;
await context.SaveChangesAsync(); await context.SaveChangesAsync();
} }
@ -103,30 +103,30 @@ namespace Hcs.WebApp.Services
} }
} }
public async Task SetCampaignEndedAsync(int campaignId) public async Task SetCampaignEndedAsync(int campaignId, DateTime endedAt)
{ {
using var context = GetNewContext(); using var context = GetNewContext();
await SetCampaignEndedAsync(context, campaignId); await SetCampaignEndedAsync(context, campaignId, endedAt);
} }
public async Task SetCampaignEndedAsync(HcsDbContext context, int campaignId) public async Task SetCampaignEndedAsync(HcsDbContext context, int campaignId, DateTime endedAt)
{ {
var campaign = await context.Campaigns.FirstOrDefaultAsync(x => x.Id == campaignId); var campaign = await context.Campaigns.FirstOrDefaultAsync(x => x.Id == campaignId);
if (campaign != null) if (campaign != null)
{ {
campaign.EndedAt = DateTime.UtcNow; campaign.EndedAt = endedAt;
await context.SaveChangesAsync(); await context.SaveChangesAsync();
} }
} }
public async Task SetCampaignEndedWithFailAsync(int campaignId, string failureReason) public async Task SetCampaignEndedWithFailAsync(int campaignId, DateTime endedAt, string failureReason)
{ {
using var context = GetNewContext(); using var context = GetNewContext();
var campaign = await context.Campaigns.FirstOrDefaultAsync(x => x.Id == campaignId); var campaign = await context.Campaigns.FirstOrDefaultAsync(x => x.Id == campaignId);
if (campaign != null) if (campaign != null)
{ {
campaign.EndedAt = DateTime.UtcNow; campaign.EndedAt = endedAt;
campaign.FailureReason = failureReason; campaign.FailureReason = failureReason;
await context.SaveChangesAsync(); await context.SaveChangesAsync();