using DotBased.Logging; using Manager.App.Extensions; using Manager.App.Services; using Microsoft.AspNetCore.Components; namespace Manager.App.Components.Pages; public partial class Services : ComponentBase { private const int VisibleEventCapacity = 500; private string _searchText = ""; private List _backgroundServices = []; private List _serviceEvents = []; private CancellationTokenSource _cts = new(); protected override void OnInitialized() { _backgroundServices = ServiceManager.GetServices(); _ = Task.Run(() => ReadEventStreamsAsync(_cts.Token)); } private Func QuickFilter => x => string.IsNullOrWhiteSpace(_searchText) || $"{x.Name} {x.Description} {x.State} {x.ExecuteInterval}".Contains(_searchText); private async Task ReadEventStreamsAsync(CancellationToken token) { if (_backgroundServices.Count == 0) { return; } var totalToGet = VisibleEventCapacity / _backgroundServices.Count; _serviceEvents.AddRange(_backgroundServices.SelectMany(x => x.ProgressEvents.Items.TakeLast(totalToGet))); var asyncEnumerators = _backgroundServices.Select(x => x.ProgressEvents.GetStreamAsync()); await foreach (var serviceEvent in AsyncEnumerableExtensions.Merge(asyncEnumerators, token)) { if (!_serviceEvents.Contains(serviceEvent)) { _serviceEvents.Add(serviceEvent); } if (_serviceEvents.Count > VisibleEventCapacity) { _serviceEvents.RemoveAt(0); } await InvokeAsync(StateHasChanged); } } private string GetLogClass(ServiceEvent serviceEvent) => serviceEvent.Severity switch { LogSeverity.Info => "log-info", LogSeverity.Warning => "log-warning", LogSeverity.Error => "log-error", _ => "log-info" }; public void Dispose() { _cts.Cancel(); _cts.Dispose(); } }