示例#1
0
        ProjectionStream LoadProjectionStream(Type projectionType, IBlobId projectionId)
        {
            string projectionName = projectionType.GetContractId();

            ReadResult <ProjectionVersions> result = GetProjectionVersions(projectionName);

            if (result.IsSuccess)
            {
                ProjectionVersion liveVersion = result.Data.GetLive();
                if (liveVersion is null)
                {
                    log.Warn(() => $"Unable to find projection `live` version. ProjectionId:{projectionId} ProjectionName:{projectionName} ProjectionType:{projectionType.Name}{Environment.NewLine}AvailableVersions:{Environment.NewLine}{result.Data.ToString()}");
                    return(ProjectionStream.Empty());
                }

                ISnapshot snapshot = null;
                if (projectionType.IsSnapshotable())
                {
                    snapshot = snapshotStore.Load(projectionName, projectionId, liveVersion);
                }
                else
                {
                    snapshot = new NoSnapshot(projectionId, projectionName);
                }

                return(LoadProjectionStream(projectionType, liveVersion, projectionId, snapshot));
            }

            return(ProjectionStream.Empty());
        }
示例#2
0
        public IProjectionGetResult <T> Get <T>(IBlobId projectionId) where T : IProjectionDefinition
        {
            if (ReferenceEquals(null, projectionId))
            {
                throw new ArgumentNullException(nameof(projectionId));
            }

            Type   projectionType = typeof(T);
            string contractId     = projectionType.GetContractId();

            try
            {
                ProjectionVersion liveVersion = GetProjectionVersions(contractId).GetLive();
                if (ReferenceEquals(null, liveVersion))
                {
                    log.Warn(() => $"Unable to find `live` version for projection with contract id {contractId} and name {projectionType.Name}");
                    return(new ProjectionGetResult <T>(default(T)));
                }

                ISnapshot                snapshot    = snapshotStore.Load(contractId, projectionId, liveVersion);
                ProjectionStream         stream      = LoadProjectionStream(projectionType, liveVersion, projectionId, snapshot);
                IProjectionGetResult <T> queryResult = stream.RestoreFromHistory <T>();

                return(queryResult);
            }
            catch (Exception ex)
            {
                log.ErrorException($"Unable to load projection. ProjectionId:{projectionId} ProjectionContractId:{contractId} ProjectionName:{projectionType.Name}", ex);
                return(new ProjectionGetResult <T>(default(T)));
            }
        }
示例#3
0
        async Task <ProjectionStream> LoadProjectionStreamAsync(Type projectionType, IBlobId projectionId)
        {
            string projectionName = projectionType.GetContractId();

            ReadResult <ProjectionVersions> result = GetProjectionVersions(projectionName);

            if (result.IsSuccess)
            {
                ProjectionVersion liveVersion = result.Data.GetLive();
                if (liveVersion is null)
                {
                    log.Warn(() => $"Unable to find projection `live` version. ProjectionId:{projectionId} ProjectionName:{projectionName} ProjectionType:{projectionType.Name}");
                    return(ProjectionStream.Empty());
                }

                ISnapshot snapshot = null;
                if (projectionType.IsSnapshotable())
                {
                    snapshot = snapshotStore.Load(projectionName, projectionId, liveVersion);
                }
                else
                {
                    snapshot = new NoSnapshot(projectionId, projectionName);
                }

                ProjectionStream stream = await LoadProjectionStreamAsync(projectionType, liveVersion, projectionId, snapshot);

                return(stream);
            }

            return(ProjectionStream.Empty());
        }
示例#4
0
        private async Task <ProjectionStream> LoadProjectionStreamAsync(ProjectionVersion version, IBlobId projectionId, ISnapshot snapshot)
        {
            bool             shouldLoadMore = true;
            Func <ISnapshot> loadSnapshot   = () => snapshot;

            List <ProjectionCommit> projectionCommits = new List <ProjectionCommit>();
            int snapshotMarker = snapshot.Revision;

            while (shouldLoadMore)
            {
                snapshotMarker++;

                var  loadProjectionCommits   = projectionStore.LoadAsync(version, projectionId, snapshotMarker).ConfigureAwait(false);
                bool checkNextSnapshotMarker = await projectionStore.HasSnapshotMarkerAsync(version, projectionId, snapshotMarker + 1).ConfigureAwait(false);

                shouldLoadMore = checkNextSnapshotMarker;

                await foreach (var commit in loadProjectionCommits)
                {
                    projectionCommits.Add(commit);
                }
            }

            ProjectionStream stream = new ProjectionStream(projectionId, projectionCommits, loadSnapshot);

            return(stream);
        }
示例#5
0
        public async Task <ReadResult <IProjectionDefinition> > GetAsync(IBlobId projectionId, Type projectionType)
        {
            using (log.BeginScope(s => s
                                  .AddScope(Log.ProjectionName, projectionType.GetContractId())
                                  .AddScope(Log.ProjectionType, projectionType.Name)
                                  .AddScope(Log.ProjectionInstanceId, projectionId.RawId)))
            {
                if (ReferenceEquals(null, projectionId))
                {
                    throw new ArgumentNullException(nameof(projectionId));
                }

                try
                {
                    ProjectionStream stream = await LoadProjectionStreamAsync(projectionType, projectionId);

                    var readResult = new ReadResult <IProjectionDefinition>(await stream.RestoreFromHistoryAsync(projectionType).ConfigureAwait(false));
                    if (readResult.NotFound && log.IsDebugEnabled())
                    {
                        log.Debug(() => "Projection instance not found.");
                    }

                    return(readResult);
                }
                catch (Exception ex)
                {
                    log.ErrorException(ex, () => "Unable to load projection.");
                    return(ReadResult <IProjectionDefinition> .WithError(ex));
                }
            }
        }
示例#6
0
        public IProjectionGetResult <IProjectionDefinition> Get(IBlobId projectionId, Type projectionType)
        {
            if (ReferenceEquals(null, projectionId))
            {
                throw new ArgumentNullException(nameof(projectionId));
            }

            ProjectionStream stream = LoadProjectionStream(projectionType, projectionId);

            return(stream.RestoreFromHistory(projectionType));
        }
示例#7
0
        IProjectionGetResult <PersistentProjectionVersionHandler> GetProjectionVersionsFromStore(string contractId)
        {
            var versionId                   = new ProjectionVersionManagerId(contractId);
            var persistentVersionType       = typeof(PersistentProjectionVersionHandler);
            var persistentVersionContractId = persistentVersionType.GetContractId();
            var persistentVersion           = new ProjectionVersion(persistentVersionContractId, ProjectionStatus.Live, 1, persistentVersionType.GetProjectionHash());
            ProjectionStream stream         = LoadProjectionStream(persistentVersionType, persistentVersion, versionId, new NoSnapshot(versionId, contractId));
            var queryResult                 = stream.RestoreFromHistory <PersistentProjectionVersionHandler>();

            return(queryResult);
        }
示例#8
0
        ProjectionStream LoadProjectionStream(Type projectionType, ProjectionVersion projectionVersion, IBlobId projectionId, ISnapshot snapshot)
        {
            if (ReferenceEquals(null, projectionVersion))
            {
                throw new ArgumentNullException(nameof(projectionVersion));
            }
            if (ReferenceEquals(null, projectionId))
            {
                throw new ArgumentNullException(nameof(projectionId));
            }
            if (ReferenceEquals(null, snapshot))
            {
                throw new ArgumentNullException(nameof(snapshot));
            }

            ISnapshot currentSnapshot = snapshot;
            string    contractId      = projectionVersion.ProjectionName;

            List <ProjectionCommit> projectionCommits = new List <ProjectionCommit>();
            int snapshotMarker = snapshot.Revision;

            while (true)
            {
                snapshotMarker++;
                var loadedCommits = projectionStore.Load(projectionVersion, projectionId, snapshotMarker).ToList();
                projectionCommits.AddRange(loadedCommits);
                bool isSnapshotable = typeof(IAmNotSnapshotable).IsAssignableFrom(projectionType) == false;

                if (isSnapshotable && snapshotStrategy.ShouldCreateSnapshot(projectionCommits, snapshot.Revision))
                {
                    ProjectionStream checkpointStream = new ProjectionStream(projectionId, projectionCommits, currentSnapshot);
                    var       projectionState         = checkpointStream.RestoreFromHistory(projectionType).Projection.State;
                    ISnapshot newSnapshot             = new Snapshot(projectionId, contractId, projectionState, snapshot.Revision + 1);
                    snapshotStore.Save(newSnapshot, projectionVersion);
                    currentSnapshot = newSnapshot;

                    projectionCommits.Clear();

                    log.Debug(() => $"Snapshot created for projection `{contractId}` with id={projectionId} where ({loadedCommits.Count}) were zipped. Snapshot: `{snapshot.GetType().Name}`");
                }
                else if (loadedCommits.Count() < snapshotStrategy.EventsInSnapshot)
                {
                    break;
                }
                else
                {
                    log.Warn($"Potential memory leak. The system will be down fairly soon. The projection `{contractId}` with id={projectionId} loads a lot of projection commits ({loadedCommits.Count}) and snapshot `{snapshot.GetType().Name}` which puts a lot of CPU and RAM pressure. You can resolve this by configuring the snapshot settings`.");
                }
            }

            ProjectionStream stream = new ProjectionStream(projectionId, projectionCommits, currentSnapshot);

            return(stream);
        }
示例#9
0
        public IProjectionGetResult <T> Get <T>(IBlobId projectionId) where T : IProjectionDefinition
        {
            if (ReferenceEquals(null, projectionId))
            {
                throw new ArgumentNullException(nameof(projectionId));
            }

            Type projectionType = typeof(T);

            ProjectionStream stream = LoadProjectionStream(projectionType, projectionId);

            return(stream.RestoreFromHistory <T>());
        }
示例#10
0
        ProjectionStream LoadProjectionStream(Type projectionType, ProjectionVersion version, IBlobId projectionId, SnapshotMeta snapshotMeta)
        {
            Func <ISnapshot> loadSnapshot = () => snapshotStore.Load(version.ProjectionName, projectionId, version);

            List <ProjectionCommit> projectionCommits = new List <ProjectionCommit>();
            int snapshotMarker = snapshotMeta.Revision;

            while (true)
            {
                snapshotMarker++;
                var loadedCommits = projectionStore.Load(version, projectionId, snapshotMarker).ToList();
                projectionCommits.AddRange(loadedCommits);

                if (projectionType.IsSnapshotable())
                {
                    if (snapshotStrategy.ShouldCreateSnapshot(projectionCommits, snapshotMeta.Revision))
                    {
                        ProjectionStream checkpointStream = new ProjectionStream(projectionId, projectionCommits, loadSnapshot);
                        var       projectionState         = checkpointStream.RestoreFromHistory(projectionType).State;
                        ISnapshot newSnapshot             = new Snapshot(projectionId, version.ProjectionName, projectionState, snapshotMeta.Revision + 1);
                        snapshotStore.Save(newSnapshot, version);
                        loadSnapshot = () => newSnapshot;

                        projectionCommits.Clear();

                        log.Debug(() => $"Snapshot created for projection `{version.ProjectionName}` with id={projectionId} where ({loadedCommits.Count}) were zipped. Snapshot: `{newSnapshot.GetType().Name}`");
                    }
                }
                else
                {
                    loadSnapshot = () => new NoSnapshot(projectionId, version.ProjectionName);
                }

                if (loadedCommits.Count < snapshotStrategy.EventsInSnapshot)
                {
                    break;
                }

                if (loadedCommits.Count > snapshotStrategy.EventsInSnapshot * 1.5)
                {
                    log.Warn(() => $"Potential memory leak. The system will be down fairly soon. The projection `{version.ProjectionName}` with id={projectionId} loads a lot of projection commits ({loadedCommits.Count}) which puts a lot of CPU and RAM pressure. You can resolve this by configuring the snapshot settings`.");
                }
            }

            ProjectionStream stream = new ProjectionStream(projectionId, projectionCommits, loadSnapshot);

            return(stream);
        }
示例#11
0
        public ReadResult <IProjectionDefinition> Get(IBlobId projectionId, Type projectionType)
        {
            if (ReferenceEquals(null, projectionId))
            {
                throw new ArgumentNullException(nameof(projectionId));
            }

            try
            {
                ProjectionStream stream = LoadProjectionStream(projectionType, projectionId);
                return(new ReadResult <IProjectionDefinition>(stream.RestoreFromHistory(projectionType)));
            }
            catch (Exception ex)
            {
                log.ErrorException($"Unable to load projection. {projectionType.Name}({projectionId})", ex);
                return(ReadResult <IProjectionDefinition> .WithError(ex));
            }
        }
示例#12
0
        ReadResult <ProjectionVersionsHandler> GetProjectionVersionsFromStore(string projectionName)
        {
            try
            {
                var persistentVersionType             = typeof(ProjectionVersionsHandler);
                var projectionVersions_ProjectionName = persistentVersionType.GetContractId();

                var versionId           = new ProjectionVersionManagerId(projectionName, context.Tenant);
                var persistentVersion   = new ProjectionVersion(projectionVersions_ProjectionName, ProjectionStatus.Live, 1, projectionHasher.CalculateHash(persistentVersionType));
                ProjectionStream stream = LoadProjectionStream(persistentVersionType, persistentVersion, versionId, new NoSnapshot(versionId, projectionVersions_ProjectionName).GetMeta());
                var queryResult         = stream.RestoreFromHistory <ProjectionVersionsHandler>();

                return(new ReadResult <ProjectionVersionsHandler>(queryResult));
            }
            catch (Exception ex)
            {
                return(ReadResult <ProjectionVersionsHandler> .WithNotFoundHint(ex.Message));
            }
        }
示例#13
0
        public ReadResult <T> Get <T>(IBlobId projectionId) where T : IProjectionDefinition
        {
            try
            {
                if (ReferenceEquals(null, projectionId))
                {
                    throw new ArgumentNullException(nameof(projectionId));
                }

                Type projectionType = typeof(T);

                ProjectionStream stream = LoadProjectionStream(projectionType, projectionId);
                return(new ReadResult <T>(stream.RestoreFromHistory <T>()));
            }
            catch (Exception ex)
            {
                log.ErrorException($"Unable to load projection. {typeof(T).Name}({projectionId})", ex);
                return(ReadResult <T> .WithError(ex));
            }
        }
        public async Task <ReadResult <T> > GetAsync <T>(IBlobId projectionId) where T : IProjectionDefinition
        {
            if (ReferenceEquals(null, projectionId))
            {
                throw new ArgumentNullException(nameof(projectionId));
            }

            try
            {
                Type projectionType = typeof(T);

                ProjectionStream stream = await LoadProjectionStreamAsync(projectionType, projectionId);

                return(new ReadResult <T>(stream.RestoreFromHistory <T>()));
            }
            catch (Exception ex)
            {
                log.ErrorException(ex, () => $"Unable to load projection. {typeof(T).Name}({projectionId})");
                return(ReadResult <T> .WithError(ex));
            }
        }
示例#15
0
        private async Task <ReadResult <ProjectionVersionsHandler> > GetProjectionVersionsFromStoreAsync(string projectionName)
        {
            try
            {
                var persistentVersionType             = typeof(ProjectionVersionsHandler);
                var projectionVersions_ProjectionName = persistentVersionType.GetContractId();

                var versionId           = new ProjectionVersionManagerId(projectionName, context.Tenant);
                var persistentVersion   = new ProjectionVersion(projectionVersions_ProjectionName, ProjectionStatus.Live, 1, projectionHasher.CalculateHash(persistentVersionType));
                ProjectionStream stream = await LoadProjectionStreamAsync(persistentVersionType, persistentVersion, versionId, new NoSnapshot(versionId, projectionVersions_ProjectionName).GetMeta()).ConfigureAwait(false);

                var queryResult = await stream.RestoreFromHistoryAsync <ProjectionVersionsHandler>().ConfigureAwait(false);

                return(new ReadResult <ProjectionVersionsHandler>(queryResult));
            }
            catch (Exception ex)
            {
                log.WarnException(ex, () => $"Failed to load projection versions. ProjectionName: {projectionName}");
                return(ReadResult <ProjectionVersionsHandler> .WithError(ex.Message));
            }
        }
示例#16
0
        public void Save(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 contractId = projectionType.GetContractId();
            var    instance   = FastActivator.CreateInstance(projectionType);

            var statefullProjection = instance as IProjectionDefinition;

            if (statefullProjection != null)
            {
                var projectionIds = statefullProjection.GetProjectionIds(@event);

                foreach (var version in GetProjectionVersions(contractId))
                {
                    foreach (var projectionId in projectionIds)
                    {
                        ISnapshot        snapshot         = snapshotStore.Load(contractId, projectionId, version);
                        ProjectionStream projectionStream = LoadProjectionStream(projectionType, version, projectionId, snapshot);
                        int snapshotMarker = snapshotStrategy.GetSnapshotMarker(projectionStream.Commits, snapshot.Revision);

                        var commit = new ProjectionCommit(projectionId, version, @event, snapshotMarker, eventOrigin, DateTime.UtcNow);
                        projectionStore.Save(commit);
                    }
                }
            }
        }
示例#17
0
        private async Task <ProjectionStream> LoadProjectionStreamAsync(Type projectionType, IBlobId projectionId)
        {
            string projectionName = projectionType.GetContractId();

            ReadResult <ProjectionVersions> result = await GetProjectionVersionsAsync(projectionName).ConfigureAwait(false);

            if (result.IsSuccess)
            {
                ProjectionVersion liveVersion = result.Data.GetLive();
                if (liveVersion is null)
                {
                    log.Warn(() => $"Unable to find projection `live` version. {Environment.NewLine}AvailableVersions:{Environment.NewLine}{result.Data.ToString()}");
                    return(ProjectionStream.Empty());
                }

                ISnapshot snapshot = projectionType.IsSnapshotable()
                    ? await snapshotStore.LoadAsync(projectionName, projectionId, liveVersion).ConfigureAwait(false)
                    : new NoSnapshot(projectionId, projectionName);

                return(await LoadProjectionStreamAsync(liveVersion, projectionId, snapshot));
            }

            return(ProjectionStream.Empty());
        }
示例#18
0
        ProjectionStream LoadProjectionStream(Type projectionType, IBlobId projectionId)
        {
            string projectionName = projectionType.GetContractId();

            try
            {
                ProjectionVersion liveVersion = GetProjectionVersions(projectionName).GetLive();
                if (ReferenceEquals(null, liveVersion))
                {
                    log.Warn(() => $"Unable to find `live` version for projection with contract id {projectionName} and name {projectionType.Name}");
                    return(ProjectionStream.Empty());
                }

                ISnapshot        snapshot = snapshotStore.Load(projectionName, projectionId, liveVersion);
                ProjectionStream stream   = LoadProjectionStream(projectionType, liveVersion, projectionId, snapshot);

                return(stream);
            }
            catch (Exception ex)
            {
                log.ErrorException($"Unable to load projection stream. ProjectionId:{projectionId} ProjectionContractId:{projectionName} ProjectionName:{projectionType.Name}", ex);
                return(ProjectionStream.Empty());
            }
        }
示例#19
0
        public void Save(Type projectionType, CronusMessage cronusMessage)
        {
            if (ReferenceEquals(null, projectionType))
            {
                throw new ArgumentNullException(nameof(projectionType));
            }
            if (ReferenceEquals(null, cronusMessage))
            {
                throw new ArgumentNullException(nameof(cronusMessage));
            }

            var projection = FastActivator.CreateInstance(projectionType) as IProjectionDefinition;

            if (projection != null)
            {
                var    projectionIds = projection.GetProjectionIds(cronusMessage.Payload as IEvent);
                string contractId    = projectionType.GetContractId();

                foreach (var projectionId in projectionIds)
                {
                    foreach (var version in GetProjectionVersions(contractId))
                    {
                        ISnapshot        snapshot         = snapshotStore.Load(contractId, projectionId, version);
                        ProjectionStream projectionStream = LoadProjectionStream(projectionType, version, projectionId, snapshot);
                        int snapshotMarker = snapshotStrategy.GetSnapshotMarker(projectionStream.Commits, snapshot.Revision);

                        EventOrigin eventOrigin = cronusMessage.GetEventOrigin();
                        DateTime    timestamp   = DateTime.UtcNow;
                        IEvent      @event      = cronusMessage.Payload as IEvent;

                        var commit = new ProjectionCommit(projectionId, version, @event, snapshotMarker, eventOrigin, timestamp);
                        projectionStore.Save(commit);
                    }
                }
            }
        }
示例#20
0
        public void Save(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)
                {
                    ReadResult <ProjectionVersions> result = GetProjectionVersions(projectionName);
                    if (result.IsSuccess)
                    {
                        foreach (ProjectionVersion version in result.Data)
                        {
                            if (version.Status == ProjectionStatus.Building || version.Status == ProjectionStatus.Live)
                            {
                                try
                                {
                                    SnapshotMeta snapshotMeta = null;
                                    if (projectionType.IsSnapshotable())
                                    {
                                        snapshotMeta = snapshotStore.LoadMeta(projectionName, projectionId, version);
                                    }
                                    else
                                    {
                                        snapshotMeta = new NoSnapshot(projectionId, projectionName).GetMeta();
                                    }
                                    ProjectionStream projectionStream = LoadProjectionStream(projectionType, version, projectionId, snapshotMeta);
                                    int snapshotMarker = snapshotStrategy.GetSnapshotMarker(projectionStream.Commits, snapshotMeta.Revision);

                                    var commit = new ProjectionCommit(projectionId, version, @event, snapshotMarker, eventOrigin, DateTime.UtcNow);
                                    projectionStore.Save(commit);
                                }
                                catch (Exception ex)
                                {
                                    log.ErrorException("Failed to persist event." + Environment.NewLine + $"\tProjectionVersion:{version}" + Environment.NewLine + $"\tEvent:{@event}", ex);
                                }
                            }
                            else if (version.Status == ProjectionStatus.NotPresent)
                            {
                                var commit = new ProjectionCommit(projectionId, version, @event, 1, eventOrigin, DateTime.UtcNow);
                                projectionStore.Save(commit);
                            }
                        }
                    }
                }
            }
        }
示例#21
0
        public void Save(Type projectionType, IEvent @event, EventOrigin eventOrigin, ProjectionVersion version)
        {
            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));
            }
            if (ReferenceEquals(null, version))
            {
                throw new ArgumentNullException(nameof(version));
            }

            if ((version.Status == ProjectionStatus.Building || version.Status == ProjectionStatus.Live) == false)
            {
                throw new ArgumentException("Invalid version. Only versions in `Building` and `Live` status are eligable for persistence.", nameof(version));
            }

            string projectionName = projectionType.GetContractId();

            if (projectionName.Equals(version.ProjectionName, StringComparison.OrdinalIgnoreCase) == false)
            {
                throw new ArgumentException($"Invalid version. The version `{version}` does not match projection `{projectionName}`", nameof(version));
            }

            var handlerInstance = handlerFactory.Create(projectionType);
            var projection      = handlerInstance.Current as IProjectionDefinition;

            if (projection != null)
            {
                var projectionIds = projection.GetProjectionIds(@event);

                foreach (var projectionId in projectionIds)
                {
                    try
                    {
                        SnapshotMeta snapshotMeta = null;
                        if (projectionType.IsSnapshotable())
                        {
                            snapshotMeta = snapshotStore.LoadMeta(projectionName, projectionId, version);
                        }
                        else
                        {
                            snapshotMeta = new NoSnapshot(projectionId, projectionName).GetMeta();
                        }
                        ProjectionStream projectionStream = LoadProjectionStream(projectionType, version, projectionId, snapshotMeta);
                        int snapshotMarker = snapshotStrategy.GetSnapshotMarker(projectionStream.Commits, snapshotMeta.Revision);

                        var commit = new ProjectionCommit(projectionId, version, @event, snapshotMarker, eventOrigin, DateTime.UtcNow);
                        projectionStore.Save(commit);
                    }
                    catch (Exception ex)
                    {
                        log.ErrorException("Failed to persist event." + Environment.NewLine + $"\tProjectionVersion:{version}" + Environment.NewLine + $"\tEvent:{@event}", ex);
                    }
                }
            }
        }