Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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));
            }
        }