public async Task <bool> ShouldBeRetriedAsync(ProjectionVersion version) { bool isVersionTrackerMissing = await IsVersionTrackerMissingAsync().ConfigureAwait(false); if (isVersionTrackerMissing) { InitializeNewProjectionVersion(); if (version.ProjectionName.Equals(ProjectionVersionsHandler.ContractId, StringComparison.OrdinalIgnoreCase) == false) { return(true); } } IndexStatus indexStatus = await GetIndexStatusAsync <EventToAggregateRootId>().ConfigureAwait(false); Type projectionType = version.ProjectionName.GetTypeByContract(); if (isVersionTrackerMissing && IsNotSystemProjection(projectionType)) { return(true); } if (indexStatus.IsNotPresent() && IsNotSystemProjection(projectionType)) { return(true); } return(false); }
public ReplayResult Rebuild(ProjectionVersion version, DateTime rebuildUntil) { if (ReferenceEquals(null, version)) { throw new ArgumentNullException(nameof(version)); } Type projectionType = version.ProjectionName.GetTypeByContract(); try { IndexStatus indexStatus = GetIndexStatus <EventToAggregateRootId>(); if (indexStatus.IsNotPresent() && IsNotSystemProjection(projectionType)) { return(ReplayResult.RetryLater($"The index is not present")); } if (IsVersionTrackerMissing() && IsNotSystemProjection(projectionType)) { return(ReplayResult.RetryLater($"Projection `{version}` still don't have present index.")); //WHEN TO RETRY AGAIN } if (HasReplayTimeout(rebuildUntil)) { return(ReplayResult.Timeout($"Rebuild of projection `{version}` has expired. Version:{version} Deadline:{rebuildUntil}.")); } var allVersions = GetAllVersions(version); if (allVersions.IsOutdatad(version)) { return(new ReplayResult($"Version `{version}` is outdated. There is a newer one which is already live.")); } if (allVersions.IsCanceled(version)) { return(new ReplayResult($"Version `{version}` was canceled.")); } DateTime startRebuildTimestamp = DateTime.UtcNow; int progressCounter = 0; logger.Info(() => $"Start rebuilding projection `{version.ProjectionName}` for version {version}. Deadline is {rebuildUntil}"); Dictionary <int, string> processedAggregates = new Dictionary <int, string>(); projectionStoreInitializer.Initialize(version); var projectionHandledEventTypes = GetInvolvedEvents(projectionType); foreach (var eventType in projectionHandledEventTypes) { logger.Info(() => $"Rebuilding projection `{version.ProjectionName}` for version {version} using eventType `{eventType}`. Deadline is {rebuildUntil}"); IEnumerable <IndexRecord> indexRecords = index.EnumerateRecords(eventType); foreach (IndexRecord indexRecord in indexRecords) { // TODO: (5) Decorator pattern which will give us the tracking progressCounter++; if (progressCounter % 1000 == 0) { logger.Info(() => $"Rebuilding projection {version.ProjectionName} => PROGRESS:{progressCounter} Version:{version} EventType:{eventType} Deadline:{rebuildUntil} Total minutes working:{(DateTime.UtcNow - startRebuildTimestamp).TotalMinutes}. logId:{Guid.NewGuid().ToString()} ProcessedAggregatesSize:{processedAggregates.Count}"); } int aggreagteRootIdHash = indexRecord.AggregateRootId.GetHashCode(); if (processedAggregates.ContainsKey(aggreagteRootIdHash)) { continue; } processedAggregates.Add(aggreagteRootIdHash, null); string mess = Encoding.UTF8.GetString(indexRecord.AggregateRootId); IAggregateRootId arId = GetAggregateRootId(mess); EventStream stream = eventStore.Load(arId); foreach (AggregateCommit arCommit in stream.Commits) { for (int i = 0; i < arCommit.Events.Count; i++) { IEvent theEvent = arCommit.Events[i].Unwrap(); if (projectionHandledEventTypes.Contains(theEvent.GetType().GetContractId())) // filter out the events which are not part of the projection { var origin = new EventOrigin(mess, arCommit.Revision, i, arCommit.Timestamp); projectionWriter.Save(projectionType, theEvent, origin, version); } } } } } logger.Info(() => $"Finish rebuilding projection `{projectionType.Name}` for version {version}. Deadline was {rebuildUntil}"); return(new ReplayResult()); } catch (Exception ex) { string message = $"Unable to replay projection. Version:{version} ProjectionType:{projectionType.FullName}"; logger.ErrorException(ex, () => message); return(new ReplayResult(message + Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace)); } }