Esempio n. 1
0
        public void Save(Type projectionType, CronusMessage 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);
                    }
                }
            }
        }
Esempio n. 2
0
        public void Save(Type projectionType, IEvent @event, EventOrigin 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);
                    }
                }
            }
        }
Esempio n. 3
0
        public void Throws_on_read_timeout()
        {
            bool checkpointRead = false;

            var reader = Sys.ActorOf(conf =>
            {
                conf.Receive <ReadProjectionCheckpointRequest>((r, ctx) =>
                {
                    ctx.Sender.Tell(new ReadProjectionCheckpointResponse(r.RequestID, 0));
                    checkpointRead = true;
                });
            });

            var options = new GlobalOptions
            {
                ReadRequestTimeout = TimeSpan.FromMilliseconds(300)
            };

            var props = ProjectionStream.CreateProps(new ProjectionStreamQuery(), reader, ActorRefs.Nobody, options);

            Sys.ActorOf(c =>
            {
                c.OnPreStart = ctx => ctx.ActorOf(props);
                c.Strategy   = new OneForOneStrategy(ex =>
                {
                    TestActor.Tell(ex);
                    return(Directive.Stop);
                });
            });

            ExpectMsg <Exception>();
            Assert.True(checkpointRead);
        }
Esempio n. 4
0
        public void Requests_checkpoint_on_start()
        {
            var reader = CreateTestProbe();
            var props  = ProjectionStream.CreateProps(new ProjectionStreamQuery(), reader, ActorRefs.Nobody, new GlobalOptions());

            Sys.ActorOf(props);

            reader.ExpectMsg <ReadProjectionCheckpointRequest>();
        }
Esempio n. 5
0
        public void Sends_ProjectionReplayFinished_to_uptodate_subscriber()
        {
            var reader     = CreateWorkingReader();
            var query      = new ProjectionStreamQuery();
            var props      = ProjectionStream.CreateProps(query, reader, ActorRefs.Nobody, new GlobalOptions());
            var ps         = Sys.ActorOf(props);
            var subscriber = CreateTestProbe();

            ps.Tell(new ProjectionSubscriptionRequest(query, 0), subscriber);
            subscriber.ExpectMsg <ProjectionReplayFinished>();
        }
Esempio n. 6
0
        public void Sends_RebuildProjection_to_subscriber_with_unknown_sequence()
        {
            var reader     = CreateWorkingReader(0);
            var query      = new ProjectionStreamQuery();
            var props      = ProjectionStream.CreateProps(query, reader, ActorRefs.Nobody, new GlobalOptions());
            var ps         = Sys.ActorOf(props);
            var subscriber = CreateTestProbe();

            // projection stream only knows event 0, projection says it knows 99
            ps.Tell(new ProjectionSubscriptionRequest(query, 99), subscriber);
            subscriber.ExpectMsg <RebuildProjection>();
        }
Esempio n. 7
0
        public void Requests_events_after_checkpoint()
        {
            var reader = Sys.ActorOf(conf =>
            {
                conf.Receive <ReadProjectionCheckpointRequest>((r, ctx) => ctx.Sender.Tell(new ReadProjectionCheckpointResponse(r.RequestID, 0)));
                conf.Receive <ReadRequest>((r, ctx) => TestActor.Forward(r));
            });

            var props = ProjectionStream.CreateProps(new ProjectionStreamQuery(), reader, ActorRefs.Nobody, new GlobalOptions());

            Sys.ActorOf(props);

            ExpectMsg <ReadRequest>();
        }
Esempio n. 8
0
        public void SubscriptionRequest_with_past_sequence_starts_projection_replay_worker()
        {
            var workerProps = Props.Create <ProbeRelay>(TestActor);

            var reader = CreateWorkingReader(1);
            var query  = new ProjectionStreamQuery(new DomainEventPredicate(typeof(TestEvent)));
            var props  = ProjectionStream.CreateProps(query, reader, ActorRefs.Nobody, new GlobalOptions(), workerProps);
            var ps     = Sys.ActorOf(props);

            var subscriber = CreateTestProbe();

            ps.Tell(new ProjectionSubscriptionRequest(query, 0), subscriber);

            ExpectMsg <InitializeProjectionReplayWorker>();
        }
Esempio n. 9
0
        public void Requests_matched_events_be_written_to_index()
        {
            var query  = new ProjectionStreamQuery(new DomainEventPredicate(typeof(TestEvent)));
            var writer = CreateTestProbe();
            var props  = ProjectionStream.CreateProps(query, CreateWorkingReader(), writer, new GlobalOptions());
            var ps     = Sys.ActorOf(props);

            ps.Tell(MockPersistedEvent.Create(new object(), 1));
            ps.Tell(MockPersistedEvent.Create(new TestEvent(), 2));
            ps.Tell(MockPersistedEvent.Create(new object(), 3));
            ps.Tell(MockPersistedEvent.Create(new TestEvent(), 4));
            ps.Tell(MockPersistedEvent.Create(new object(), 5));

            writer.ExpectMsg <ProjectionIndexPersistenceRequest>(m => m.ProjectionStream.Equals(query.ProjectionStream) && m.ProjectionStreamSequence == 1 && m.GlobalSequence == 2);
            writer.ExpectMsg <ProjectionIndexPersistenceRequest>(m => m.ProjectionStream.Equals(query.ProjectionStream) && m.ProjectionStreamSequence == 2 && m.GlobalSequence == 4);
            writer.ExpectNoMsg(TimeSpan.FromMilliseconds(500));
        }
Esempio n. 10
0
        ProjectionVersions GetProjectionVersions(string contractId)
        {
            ProjectionVersions versions = inMemoryVersionStore.Get(contractId);

            if (versions == null || versions.Count == 0)
            {
                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(typeof(PersistentProjectionVersionHandler), persistentVersion, versionId, new NoSnapshot(versionId, contractId));
                var queryResult                 = stream.RestoreFromHistory <PersistentProjectionVersionHandler>();
                if (queryResult.Success)
                {
                    if (queryResult.Projection.State.Live != null)
                    {
                        inMemoryVersionStore.Cache(queryResult.Projection.State.Live);
                    }
                    if (queryResult.Projection.State.Building != null)
                    {
                        inMemoryVersionStore.Cache(queryResult.Projection.State.Building);
                    }
                    versions = inMemoryVersionStore.Get(contractId);
                }

                // inception
                if (versions == null || versions.Count == 0)
                {
                    if (string.Equals(persistentVersionContractId, contractId, StringComparison.OrdinalIgnoreCase))
                    {
                        inMemoryVersionStore.Cache(persistentVersion);
                        versions = inMemoryVersionStore.Get(contractId);
                    }
                    else
                    {
                        var initialVersion = new ProjectionVersion(contractId, ProjectionStatus.Building, 1, contractId.GetTypeByContract().GetProjectionHash());
                        inMemoryVersionStore.Cache(initialVersion);
                        versions = inMemoryVersionStore.Get(contractId);
                    }
                }
            }

            return(versions ?? new ProjectionVersions());
        }
Esempio n. 11
0
        public async Task Sends_ProjectionUnsubscribed_to_subscribers_on_restart()
        {
            var query  = new ProjectionStreamQuery();
            var reader = CreateWorkingReader();
            var props  = ProjectionStream.CreateProps(query, reader, ActorRefs.Nobody, new GlobalOptions());
            var ps     = Sys.ActorOf(props);

            var subscriber = Sys.ActorOf(conf =>
            {
                conf.Receive <ProjectionReplayFinished>((m, ctx) => { });
                conf.ReceiveAny((o, ctx) => TestActor.Forward(o));
            });

            ps.Tell(new ProjectionSubscriptionRequest(query, 0), subscriber);
            await Task.Delay(100);

            ps.Tell(Kill.Instance);

            ExpectMsg <ProjectionUnsubscribed>();
        }
Esempio n. 12
0
        public void Throws_on_checkpoint_abort()
        {
            var reader = Sys.ActorOf(conf =>
            {
                conf.Receive <ReadProjectionCheckpointRequest>((r, ctx) => ctx.Sender.Tell(new Aborted(r.RequestID, new Exception())));
            });

            var props = ProjectionStream.CreateProps(new ProjectionStreamQuery(), reader, ActorRefs.Nobody, new GlobalOptions());

            Sys.ActorOf(c =>
            {
                c.OnPreStart = ctx => ctx.ActorOf(props);
                c.Strategy   = new OneForOneStrategy(ex =>
                {
                    TestActor.Tell(ex);
                    return(Directive.Stop);
                });
            });

            ExpectMsg <Exception>();
        }
Esempio n. 13
0
        public IProjectionGetResult <T> Get <T>(IBlobId projectionId) where T : IProjectionDefinition
        {
            try
            {
                Type   projectionType = typeof(T);
                string contractId     = projectionType.GetContractId();

                ProjectionVersion liveVersion = GetProjectionVersions(contractId).GetLive();

                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(ex.Message, ex);
                return(new ProjectionGetResult <T>(default(T)));
            }
        }
Esempio n. 14
0
        public void Throws_on_checkpoint_timeout()
        {
            var options = new GlobalOptions
            {
                ReadRequestTimeout = TimeSpan.FromMilliseconds(300)
            };

            var props = ProjectionStream.CreateProps(new ProjectionStreamQuery(), ActorRefs.Nobody, ActorRefs.Nobody, options);

            Sys.ActorOf(c =>
            {
                c.OnPreStart = ctx => ctx.ActorOf(props);
                c.Strategy   = new OneForOneStrategy(ex =>
                {
                    TestActor.Tell(ex);
                    return(Directive.Stop);
                });
            });

            ExpectMsg <Exception>();
        }
Esempio n. 15
0
        ProjectionStream LoadProjectionStream(Type projectionType, ProjectionVersion projectionVersion, IBlobId projectionId, ISnapshot snapshot)
        {
            ISnapshot currentSnapshot = snapshot;
            string    contractId      = projectionVersion.ProjectionContractId;

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

            while (true)
            {
                snapshotMarker++;
                var loadedCommits = projectionStore.Load(projectionVersion, projectionId, snapshotMarker).ToList();
                if (loadedCommits.Count > 1000)
                {
                    log.Warn($"Potential memory leak. The system will be down fairly soon. The projection `{contractId}` for 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 enabling the Snapshots feature in the host which handles projection WRITES and READS using `.UseSnapshots(...)`.");
                }

                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();
                }
                else if (loadedCommits.Count() < snapshotStrategy.EventsInSnapshot)
                {
                    break;
                }
            }

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

            return(stream);
        }
Esempio n. 16
0
        public void Subscribers_that_received_RebuildProjection_need_to_resubscribe_to_receive_messages()
        {
            var reader = CreateWorkingReader();
            var query  = new ProjectionStreamQuery(new DomainEventPredicate(typeof(TestEvent)));
            var props  = ProjectionStream.CreateProps(query, reader, ActorRefs.Nobody, new GlobalOptions());
            var ps     = Sys.ActorOf(props);

            var subscriber = Sys.ActorOf(conf =>
            {
                conf.Receive <RebuildProjection>((r, ctx) => { });
                conf.ReceiveAny((o, ctx) => TestActor.Forward(o));
            });

            // subscribe with invalid sequence
            ps.Tell(new ProjectionSubscriptionRequest(query, 10), subscriber);

            //publish to event stream
            var e = MockPersistedEvent.Create(new TestEvent());

            Sys.EventStream.Publish(e);

            // expects the domain event to be the same
            ExpectNoMsg(TimeSpan.FromSeconds(1));
        }
Esempio n. 17
0
        public void Publishes_events_from_eventstream_to_subscribers()
        {
            var reader = CreateWorkingReader();
            var query  = new ProjectionStreamQuery(new DomainEventPredicate(typeof(TestEvent)));
            var props  = ProjectionStream.CreateProps(query, reader, ActorRefs.Nobody, new GlobalOptions());
            var ps     = Sys.ActorOf(props);

            var subscriber = Sys.ActorOf(conf =>
            {
                conf.Receive <ProjectionReplayFinished>((r, ctx) => { });
                conf.ReceiveAny((o, ctx) => TestActor.Forward(o));
            });

            // subscribe
            ps.Tell(new ProjectionSubscriptionRequest(query, 0), subscriber);

            //publish to event stream
            var e = MockPersistedEvent.Create(new TestEvent());

            Sys.EventStream.Publish(e);

            // expects the domain event to be the same
            ExpectMsg <IPersistedStreamEvent>(m => m.DomainEvent == e.DomainEvent, TimeSpan.FromSeconds(15));
        }