diff --git a/Hcs.WebApp/BackgroundServices/OperationExecutionService.cs b/Hcs.WebApp/BackgroundServices/OperationExecutionService.cs new file mode 100644 index 0000000..3dbb888 --- /dev/null +++ b/Hcs.WebApp/BackgroundServices/OperationExecutionService.cs @@ -0,0 +1,17 @@ +namespace Hcs.WebApp.BackgroundServices +{ + public class OperationExecutionService(OperationExecutionState state) : BackgroundService + { + private readonly OperationExecutionState state = state; + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + while (!stoppingToken.IsCancellationRequested) + { + await Task.Delay(10000, stoppingToken); + + // TODO + } + } + } +} diff --git a/Hcs.WebApp/BackgroundServices/OperationExecutionState.cs b/Hcs.WebApp/BackgroundServices/OperationExecutionState.cs new file mode 100644 index 0000000..f722f90 --- /dev/null +++ b/Hcs.WebApp/BackgroundServices/OperationExecutionState.cs @@ -0,0 +1,27 @@ +using Hcs.WebApp.Data.Hcs; +using System.Collections.Concurrent; + +namespace Hcs.WebApp.BackgroundServices +{ + public class OperationExecutionState + { + private readonly ConcurrentQueue operations = new(); + + public event Action OnOperationStarted; + + public void EnqueueOperation(Operation operation) + { + operations.Enqueue(operation); + } + + public bool TryDequeueOperation(out Operation operation) + { + return operations.TryDequeue(out operation); + } + + public void InvokeOnOperationStarted(Operation operation) + { + OnOperationStarted?.Invoke(operation); + } + } +} diff --git a/Hcs.WebApp/Components/Pages/Registry/Common.razor b/Hcs.WebApp/Components/Pages/Registry/Common.razor index b8c69ce..4aaa95c 100644 --- a/Hcs.WebApp/Components/Pages/Registry/Common.razor +++ b/Hcs.WebApp/Components/Pages/Registry/Common.razor @@ -1,18 +1,22 @@ @page "/registry/common" @using System.IdentityModel.Claims +@using Hcs.WebApp.BackgroundServices @using Hcs.WebApp.Components.Dialogs @using Hcs.WebApp.Services @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Identity @using Microsoft.EntityFrameworkCore +@implements IDisposable + @attribute [Authorize] @inject AuthenticationStateProvider AuthenticationStateProvider @inject OperationService OperationService @inject RegistryService RegistryService @inject DialogService DialogService +@inject OperationExecutionState OperationExecutionState Общие справочники подсистемы НСИ @@ -74,7 +78,6 @@ if (firstRender) { ChangeState(CommonPageState.Init); - StateHasChanged(); var finalState = CommonPageState.Idle; var state = await AuthenticationStateProvider.GetAuthenticationStateAsync(); @@ -89,16 +92,29 @@ { registries = await RegistryService.GetAllRegistries(true); } + + OperationExecutionState.OnOperationStarted += OnOperationStarted; } ChangeState(finalState); - StateHasChanged(); } } async Task SyncRegistries() { - // TODO + if (state == CommonPageState.OperationWaiting) return; + + ChangeState(CommonPageState.OperationWaiting); + + if (await OperationService.HasActiveOperation(Operation.OperationType.Nsi_15_7_0_1_ExportAllRegistryElements)) + { + ChangeState(CommonPageState.Idle); + } + else + { + var operation = await OperationService.InitiateOperation(Operation.OperationType.Nsi_15_7_0_1_ExportAllRegistryElements, ""); + OperationExecutionState.EnqueueOperation(operation); + } } async Task ViewRegistry(Registry userWithRole) @@ -118,9 +134,12 @@ void ChangeState(CommonPageState state) { + if (this.state == state) return; + this.state = state; SetSyncText(); + StateHasChanged(); } void SetSyncText() @@ -141,4 +160,17 @@ break; } } + + void OnOperationStarted(Operation operation) + { + if (operation.Type == Operation.OperationType.Nsi_15_7_0_1_ExportAllRegistryElements) + { + InvokeAsync(() => ChangeState(CommonPageState.OperationWaiting)); + } + } + + public void Dispose() + { + OperationExecutionState.OnOperationStarted -= OnOperationStarted; + } } diff --git a/Hcs.WebApp/Program.cs b/Hcs.WebApp/Program.cs index 62f998a..516948f 100644 --- a/Hcs.WebApp/Program.cs +++ b/Hcs.WebApp/Program.cs @@ -1,3 +1,4 @@ +using Hcs.WebApp.BackgroundServices; using Hcs.WebApp.Components; using Hcs.WebApp.Components.Shared; using Hcs.WebApp.Data.Hcs; @@ -60,6 +61,9 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddSingleton(); +builder.Services.AddHostedService(); + var activator = new RadzenComponentActivator(); activator.Override(typeof(RadzenDataGrid<>), typeof(LocalizedRadzenDataGrid<>)); builder.Services.AddSingleton(activator); diff --git a/Hcs.WebApp/Services/OperationService.cs b/Hcs.WebApp/Services/OperationService.cs index 4909036..4cade7f 100644 --- a/Hcs.WebApp/Services/OperationService.cs +++ b/Hcs.WebApp/Services/OperationService.cs @@ -12,5 +12,19 @@ namespace Hcs.WebApp.Services using var context = factory.CreateDbContext(); return await context.Operations.AnyAsync(x => x.Type == type && !x.EndedAt.HasValue); } + + public async Task InitiateOperation(Operation.OperationType type, string initiatorId) + { + using var context = factory.CreateDbContext(); + var operation = new Operation() + { + Type = type, + InitiatorId = initiatorId, + StartedAt = DateTime.UtcNow + }; + await context.Operations.AddAsync(operation); + await context.SaveChangesAsync(); + return operation; + } } }