/// <summary> /// Compares IInternalCache objects /// </summary> internal IEnumerable <UserEvents.MergeRequestEvent> CheckForUpdates( IInternalCache oldDetails, IInternalCache newDetails) { TwoListDifference <MergeRequestWithProject> diff = getMergeRequestDiff(oldDetails, newDetails); return(getMergeRequestUpdates(diff, oldDetails, newDetails)); }
/// <summary> /// Calculate difference between two IInternalCache objects /// </summary> private TwoListDifference <MergeRequestWithProject> getMergeRequestDiff( IInternalCache oldDetails, IInternalCache newDetails) { TwoListDifference <MergeRequestWithProject> diff = new TwoListDifference <MergeRequestWithProject> ( new List <MergeRequestWithProject>(), new List <MergeRequestWithProject>(), new List <Tuple <MergeRequestWithProject, MergeRequestWithProject> >() ); HashSet <ProjectKey> projectKeys = oldDetails.GetProjects().Concat(newDetails.GetProjects()).ToHashSet(); foreach (ProjectKey projectKey in projectKeys) { MergeRequest[] previouslyCachedMergeRequests = oldDetails.GetMergeRequests(projectKey).ToArray(); MergeRequest[] newCachedMergeRequests = newDetails.GetMergeRequests(projectKey).ToArray(); Array.Sort(previouslyCachedMergeRequests, (x, y) => x.Id.CompareTo(y.Id)); Array.Sort(newCachedMergeRequests, (x, y) => x.Id.CompareTo(y.Id)); int iPrevMR = 0, iNewMR = 0; while (iPrevMR < previouslyCachedMergeRequests.Count() && iNewMR < newCachedMergeRequests.Count()) { if (previouslyCachedMergeRequests[iPrevMR].Id < newCachedMergeRequests[iNewMR].Id) { diff.FirstOnly.Add(new MergeRequestWithProject(previouslyCachedMergeRequests[iPrevMR], projectKey)); ++iPrevMR; } else if (previouslyCachedMergeRequests[iPrevMR].Id == newCachedMergeRequests[iNewMR].Id) { diff.Common.Add(new Tuple <MergeRequestWithProject, MergeRequestWithProject>( new MergeRequestWithProject(previouslyCachedMergeRequests[iPrevMR], projectKey), new MergeRequestWithProject(newCachedMergeRequests[iNewMR], projectKey))); ++iPrevMR; ++iNewMR; } else { diff.SecondOnly.Add(new MergeRequestWithProject(newCachedMergeRequests[iNewMR], projectKey)); ++iNewMR; } } while (iPrevMR < previouslyCachedMergeRequests.Count()) { diff.FirstOnly.Add(new MergeRequestWithProject(previouslyCachedMergeRequests[iPrevMR], projectKey)); ++iPrevMR; } while (iNewMR < newCachedMergeRequests.Count()) { diff.SecondOnly.Add(new MergeRequestWithProject(newCachedMergeRequests[iNewMR], projectKey)); ++iNewMR; } } return(diff); }
public CacheUpdater(Dictionary <TKey, TObject> data, Func <TObject, TKey> keySelector = null) { if (data == null) { throw new ArgumentNullException(nameof(data)); } _cache = new InternalCache <TObject, TKey>(data); _keySelector = keySelector; }
/// <summary> /// Convert a difference between two states into a list of merge request updates splitted in new/updated/closed /// </summary> private IEnumerable <UserEvents.MergeRequestEvent> getMergeRequestUpdates( TwoListDifference <MergeRequestWithProject> diff, IInternalCache oldDetails, IInternalCache newDetails) { List <UserEvents.MergeRequestEvent> updates = new List <UserEvents.MergeRequestEvent>(); foreach (MergeRequestWithProject mergeRequest in diff.SecondOnly) { FullMergeRequestKey fmk = new FullMergeRequestKey(mergeRequest.Project, mergeRequest.MergeRequest); updates.Add(new UserEvents.MergeRequestEvent( fmk, UserEvents.MergeRequestEvent.Type.AddedMergeRequest, null)); } foreach (MergeRequestWithProject mergeRequest in diff.FirstOnly) { FullMergeRequestKey fmk = new FullMergeRequestKey(mergeRequest.Project, mergeRequest.MergeRequest); updates.Add(new UserEvents.MergeRequestEvent( fmk, UserEvents.MergeRequestEvent.Type.RemovedMergeRequest, null)); } foreach (Tuple <MergeRequestWithProject, MergeRequestWithProject> mrPair in diff.Common) { MergeRequest mergeRequest1 = mrPair.Item1.MergeRequest; MergeRequest mergeRequest2 = mrPair.Item2.MergeRequest; Debug.Assert(mergeRequest1.Id == mergeRequest2.Id); MergeRequestKey mergeRequestKey = new MergeRequestKey(mrPair.Item2.Project, mergeRequest2.IId); IEnumerable <Version> oldVersions = oldDetails.GetVersions(mergeRequestKey); IEnumerable <Version> newVersions = newDetails.GetVersions(mergeRequestKey); bool labelsUpdated = !Enumerable.SequenceEqual(mergeRequest1.Labels, mergeRequest2.Labels); bool commitsUpdated = newVersions.Count() > oldVersions.Count(); MergeRequestApprovalConfiguration oldApprovals = oldDetails.GetApprovals(mergeRequestKey); MergeRequestApprovalConfiguration newApprovals = newDetails.GetApprovals(mergeRequestKey); bool detailsUpdated = areMergeRequestsDifferentInDetails(mergeRequest1, mergeRequest2) || areApprovalsDifferent(oldApprovals, newApprovals); if (labelsUpdated || commitsUpdated || detailsUpdated) { FullMergeRequestKey fmk = new FullMergeRequestKey( mergeRequestKey.ProjectKey, mergeRequest2); updates.Add(new UserEvents.MergeRequestEvent( fmk, UserEvents.MergeRequestEvent.Type.UpdatedMergeRequest, new UserEvents.MergeRequestEvent.UpdateScope(commitsUpdated, labelsUpdated, detailsUpdated))); } } return(updates); }
async private Task <IEnumerable <UserEvents.MergeRequestEvent> > updateOneOnTimer(MergeRequestKey mrk) { if (_updating) { traceDetailed(String.Format("Cannot update !{0} in {1}", mrk.IId, mrk.ProjectKey.ProjectName)); await TaskUtils.WhileAsync(() => _updating); traceDetailed(String.Format("Skipped update for !{0} in {1}", mrk.IId, mrk.ProjectKey.ProjectName)); return(null); } IInternalCache oldDetails = _cache.Clone(); traceDetailed(String.Format("Ready to update !{0} in {1}", mrk.IId, mrk.ProjectKey.ProjectName)); try { _updating = true; if (_mergeRequestLoader != null) { await _mergeRequestLoader.LoadMergeRequest(mrk); } MergeRequestRefreshed?.Invoke(mrk); } catch (BaseLoaderException ex) { ExceptionHandlers.Handle("Cannot perform a one-shot update", ex); return(null); } finally { _updating = false; traceDetailed(String.Format("Updated !{0} in {1}", mrk.IId, mrk.ProjectKey.ProjectName)); } IEnumerable <UserEvents.MergeRequestEvent> updates = _checker.CheckForUpdates(oldDetails, _cache); int legalUpdates = updates.Count(x => x.Labels); Debug.Assert(legalUpdates == 0 || legalUpdates == 1); if (legalUpdates > 0) { traceInformation( String.Format( "Updated Labels: {0}. MRK: HostName={1}, ProjectName={2}, IId={3}", legalUpdates, mrk.ProjectKey.HostName, mrk.ProjectKey.ProjectName, mrk.IId)); } return(updates); }
async private Task <IEnumerable <UserEvents.MergeRequestEvent> > updateAllOnTimer() { if (_updating) { await TaskUtils.WhileAsync(() => _updating); return(null); } IInternalCache oldDetails = _cache.Clone(); try { _updating = true; await _mergeRequestListLoader.Load(); } catch (BaseLoaderException ex) { ExceptionHandlers.Handle("Cannot update merge requests on timer", ex); } finally { _updating = false; } IEnumerable <UserEvents.MergeRequestEvent> updates = _checker.CheckForUpdates(oldDetails, _cache); Trace.TraceInformation( String.Format( "[UpdateManager] Merge Request Updates: " + "New {0}, Updated commits {1}, Updated labels {2}, Updated details {3}, Closed {4}", updates.Count(x => x.New), updates.Count(x => x.Commits), updates.Count(x => x.Labels), updates.Count(x => x.Details), updates.Count(x => x.Closed))); return(updates); }
async private Task <IEnumerable <UserEvents.MergeRequestEvent> > updateAllOnTimer() { if (_updating) { traceDetailed("Cannot update the list"); await TaskUtils.WhileAsync(() => _updating); traceDetailed("List update has been skipped"); return(null); } IInternalCache oldDetails = _cache.Clone(); traceDetailed("Ready to update the list"); try { _updating = true; if (_mergeRequestListLoader != null) { await _mergeRequestListLoader.Load(); } MergeRequestListRefreshed?.Invoke(); } catch (BaseLoaderException ex) { ExceptionHandlers.Handle("Cannot update merge requests on timer", ex); return(null); } finally { _updating = false; traceDetailed("Updated the list"); } IEnumerable <UserEvents.MergeRequestEvent> updates = _checker.CheckForUpdates(oldDetails, _cache); int newMergeRequestsCount = updates.Count(x => x.AddedToCache); int mergeRequestsWithUpdatedCommitsCount = updates.Count(x => x.Commits); int mergeRequestsWithUpdatedLabelsCount = updates.Count(x => x.Labels); int mergeRequestsWithUpdatedDetailsCount = updates.Count(x => x.Details); int closedMergeRequestsCount = updates.Count(x => x.RemovedFromCache); if (newMergeRequestsCount > 0 || mergeRequestsWithUpdatedCommitsCount > 0 || mergeRequestsWithUpdatedLabelsCount > 0 || mergeRequestsWithUpdatedDetailsCount > 0 || closedMergeRequestsCount > 0) { traceInformation( String.Format( "Merge Request Updates: " + "New {0}, Updated commits {1}, Updated labels {2}, Updated details {3}, Closed {4}", newMergeRequestsCount, mergeRequestsWithUpdatedCommitsCount, mergeRequestsWithUpdatedLabelsCount, mergeRequestsWithUpdatedDetailsCount, closedMergeRequestsCount)); } return(updates); }
internal ImmutableGroup(TGroupKey key, IInternalCache <TObject, TKey> cache) { Key = key; _cache = new InternalCache <TObject, TKey>(cache.Count); cache.KeyValues.ForEach(kvp => _cache.AddOrUpdate(kvp.Value, kvp.Key)); }
public CacheUpdater(IInternalCache <TObject, TKey> cache, Func <TObject, TKey> keySelector = null) { _cache = cache ?? throw new ArgumentNullException(nameof(cache)); _keySelector = keySelector; }
private static IGrouping <TObject, TKey, TGroupKey> GetGroupState(TGroupKey key, IInternalCache <TObject, TKey> cache) { return(new ImmutableGroup <TObject, TKey, TGroupKey>(key, cache)); }