using C4IT.FASD.Base; using C4IT.FASD.Cockpit.Communication; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using static C4IT.Logging.cLogManager; [assembly: InternalsVisibleTo("F4SD.Cockpit.Client.Test")] namespace FasdDesktopUi.Basics.Services.RelationService { internal class RelationService : IRelationService { private readonly object _relationsLock = new object(); private IEnumerable _relations = new List(); public void Reset() { lock (_relationsLock) _relations = _relations.Where(r => r.Type == enumF4sdSearchResultClass.User).ToList(); RelationsReset?.Invoke(this, EventArgs.Empty); } /// /// Asynchronously loads relations for the specified search results. /// /// This method initiates a task to gather relations for the provided search results and /// periodically checks for the completion of the task. Once relations are retrieved, an event /// is raised to notify listeners of the progress. /// Task id and pending information classes public async Task LoadRelationsAsync(IEnumerable relatedTo, CancellationToken token = default) { try { lock (_relationsLock) _relations = relatedTo?.Select(searchResult => new cF4sdApiSearchResultRelation(searchResult)).ToList() ?? new List(); cF4sdStagedSearchResultRelationTaskId gatherRelationTask = await cFasdCockpitCommunicationBase.Instance.StartGatheringRelations(relatedTo, token); if (gatherRelationTask is null) return null; _ = Task.Run(async () => await GatherRelationsAsync(gatherRelationTask.Id, relatedTo, token)); return gatherRelationTask; } catch (Exception ex) { LogException(ex); } return null; } private async Task GatherRelationsAsync(Guid gatherTaskId, IEnumerable relatedTo, CancellationToken token = default) { try { const int maxRetryCount = 10; for (int i = 0; i < maxRetryCount; i++) { if (token.IsCancellationRequested) { await cFasdCockpitCommunicationBase.Instance.StopGatheringRelations(gatherTaskId, CancellationToken.None); return; } cF4sdStagedSearchResultRelations stagedRelations = await cFasdCockpitCommunicationBase.Instance.GetStagedRelations(gatherTaskId, token); if (stagedRelations is null) continue; stagedRelations.MergeAsRelationInfosWith(relatedTo); lock (_relationsLock) _relations = _relations.Union(stagedRelations.Relations).ToList(); RelationsFound?.Invoke(this, new StagedSearchResultRelationsEventArgs() { RelatedTo = relatedTo, StagedResultRelations = stagedRelations, RelationService = this }); if (stagedRelations?.IsComplete ?? false) break; } } catch (Exception ex) { LogException(ex); } } public IReadOnlyList GetLoadedRelations() { lock (_relationsLock) return _relations.ToList(); } public IRelationService Clone() { RelationService copy = new RelationService(); lock (_relationsLock) copy._relations = _relations.ToList(); return copy; } public event EventHandler RelationsReset; public event EventHandler RelationsFound; } }