public async Task SaveAsync(Type projectionType, IEvent @event, EventOrigin eventOrigin) { if (ReferenceEquals(null, projectionType)) { throw new ArgumentNullException(nameof(projectionType)); } if (ReferenceEquals(null, @event)) { throw new ArgumentNullException(nameof(@event)); } if (ReferenceEquals(null, eventOrigin)) { throw new ArgumentNullException(nameof(eventOrigin)); } string projectionName = projectionType.GetContractId(); var handlerInstance = handlerFactory.Create(projectionType); var projection = handlerInstance.Current as IProjectionDefinition; if (projection != null) { var projectionIds = projection.GetProjectionIds(@event); foreach (var projectionId in projectionIds) { using (log.BeginScope(s => s.AddScope("cronus_projection_id", projectionId))) { ReadResult <ProjectionVersions> result = await GetProjectionVersionsAsync(projectionName).ConfigureAwait(false); if (result.IsSuccess) { foreach (ProjectionVersion version in result.Data) { using (log.BeginScope(s => s.AddScope("cronus_projection_version", version))) { if (ShouldSaveEventForVersion(version)) { try { SnapshotMeta snapshotMeta = null; if (projectionType.IsSnapshotable()) { snapshotMeta = await snapshotStore.LoadMetaAsync(projectionName, projectionId, version).ConfigureAwait(false); } else { snapshotMeta = new NoSnapshot(projectionId, projectionName).GetMeta(); } int snapshotMarker = snapshotMeta.Revision + 2; var commit = new ProjectionCommit(projectionId, version, @event, snapshotMarker, eventOrigin, DateTime.UtcNow); await projectionStore.SaveAsync(commit).ConfigureAwait(false); } catch (Exception ex) when(LogMessageWhenFailToUpdateProjection(ex, version)) { } } } } if (result.HasError) { log.Error(() => "Failed to update projection because the projection version failed to load. Please replay the projection to restore the state. Self-heal hint!" + Environment.NewLine + result.Error + Environment.NewLine + $"\tProjectionName:{projectionName}" + Environment.NewLine + $"\tEvent:{@event}"); } } } } } }