private async Task <bool> RebuildEventsAsync(string eventTypeId, IClusterOperations cluster, CancellationToken cancellationToken) { RebuildProjection_JobData.EventPaging paging = Data.EventTypePaging.Where(et => et.Type.Equals(eventTypeId, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); unchecked { ulong pagingProcessedCount = Data.EventTypePaging.Select(p => p.ProcessedCount).DefaultIfEmpty().Aggregate((x, y) => x + y); progressTracker.Processed = pagingProcessedCount; } string paginationToken = paging?.PaginationToken; LoadIndexRecordsResult indexRecordsResult = await eventToAggregateIndex.EnumerateRecordsAsync(eventTypeId, paginationToken).ConfigureAwait(false); // TODO: Think about cassandra exception here. Such exceptions MUST be handled in the concrete impl of the IndexStore IEnumerable <EventStream> eventStreams = await rebuildingRepository.LoadEventsAsync(indexRecordsResult.Records, Data.Version).ConfigureAwait(false); await rebuildingRepository.SaveAggregateCommitsAsync(eventStreams, Data).ConfigureAwait(false); await NotifyClusterAsync(eventTypeId, indexRecordsResult.PaginationToken, cluster, cancellationToken).ConfigureAwait(false); var hasMoreRecords = indexRecordsResult.Records.Any(); return(hasMoreRecords); }
protected override async Task <JobExecutionStatus> RunJobAsync(IClusterOperations cluster, CancellationToken cancellationToken = default) { Dictionary <int, string> processedAggregates = new Dictionary <int, string>(); string eventTypeId = Data.SourceEventTypeId; bool hasMoreRecords = true; while (hasMoreRecords && Data.IsCompleted == false) { string paginationToken = Data.EventTypePaging?.PaginationToken; LoadIndexRecordsResult indexRecordsResult = await eventToAggregateIndex.EnumerateRecordsAsync(eventTypeId, paginationToken).ConfigureAwait(false); IEnumerable <IndexRecord> indexRecords = indexRecordsResult.Records; Type publicEventType = typeof(IPublicEvent); ReplayOptions opt = new ReplayOptions() { AggregateIds = indexRecordsResult.Records.Select(indexRecord => AggregateUrn.Parse(Convert.ToBase64String(indexRecord.AggregateRootId), Urn.Base64)), ShouldSelect = commit => { bool result = (from publicEvent in commit.PublicEvents let eventType = publicEvent.GetType() where publicEventType.IsAssignableFrom(eventType) where eventType.GetContractId().Equals(eventTypeId) select publicEvent) .Any(); return(result); }, After = Data.After, Before = Data.Before }; LoadAggregateCommitsResult foundAggregateCommits = await eventStorePlayer.LoadAggregateCommitsAsync(opt).ConfigureAwait(false); foreach (AggregateCommit arCommit in foundAggregateCommits.Commits) { if (cancellationToken.IsCancellationRequested) { logger.Info(() => $"Job has been cancelled."); return(JobExecutionStatus.Running); } foreach (IPublicEvent publicEvent in arCommit.PublicEvents) { if (publicEvent.GetType().GetContractId().Equals(eventTypeId)) { var headers = new Dictionary <string, string>() { { MessageHeader.RecipientBoundedContext, Data.RecipientBoundedContext }, { MessageHeader.RecipientHandlers, Data.RecipientHandlers } }; publicEventPublisher.Publish(publicEvent, headers); } } } var progress = new ReplayPublicEvents_JobData.EventTypePagingProgress(eventTypeId, indexRecordsResult.PaginationToken, 0, 0); Data.MarkEventTypeProgress(progress); Data.Timestamp = DateTimeOffset.UtcNow; Data = await cluster.PingAsync(Data, cancellationToken).ConfigureAwait(false); hasMoreRecords = indexRecordsResult.Records.Any(); } Data.IsCompleted = true; Data.Timestamp = DateTimeOffset.UtcNow; Data = await cluster.PingAsync(Data).ConfigureAwait(false); logger.Info(() => $"The job has been completed."); return(JobExecutionStatus.Completed); }