async Task MaintainIndexesCore() { FetchIntervalSeconds.RequireRange(nameof(FetchIntervalSeconds), 3, 1); while (!TokenSource.Token.IsCancellationRequested) { TokenSource.Token.ThrowIfCancellationRequested(); var fetchEndDate = DateTime.UtcNow.AddSeconds(-FetchIntervalSeconds * 2); var notChangedDuring = fetchEndDate.AddSeconds(FetchIntervalSeconds); if (ChangedSources.Count(u => u.ChangedUTCDate > fetchEndDate && u.ChangedUTCDate <= notChangedDuring) == 0) { var orderedNeedProcessingChanges = ChangedSources.Where(u => u.ChangedUTCDate <= fetchEndDate).ToList(); if (orderedNeedProcessingChanges.Count > 0) { foreach (var _ in orderedNeedProcessingChanges) { ChangedSources.TryDequeue(out var _); } ProcessingChanges(orderedNeedProcessingChanges); IndexBuilder.Commit(); TriggerCommitFinished(); } } TokenSource.Token.ThrowIfCancellationRequested(); var fetchRetryEndDate = DateTime.UtcNow.AddSeconds(-3); var needRetry = PendingRetryCodeSources.Count(u => u.LastRetryUTCDate <= fetchRetryEndDate); if (needRetry > 0) { var needRetrySources = new List <ChangedSource>(); for (var index = 0; index < needRetry; index++) { if (PendingRetryCodeSources.TryDequeue(out var pendingRetrySource)) { needRetrySources.Add(pendingRetrySource); } } ProcessingChanges(needRetrySources.OrderBy(u => u.ChangedUTCDate).ToList(), true); IndexBuilder.Commit(); } await Task.Delay(FetchIntervalSeconds * 1000, TokenSource.Token); } }