public async Task Verify_aggregation_call()
        {
            ProjectionStatusLoader sut = new ProjectionStatusLoader(Database, Database, 5);

            SampleAggregateId identity1 = new SampleAggregateId(1);
            var aggregate = await Repository.GetByIdAsync <SampleAggregate>(identity1).ConfigureAwait(false);

            aggregate.Create();
            await Repository.SaveAsync(aggregate, Guid.NewGuid().ToString(), h => { }).ConfigureAwait(false);

            SampleAggregateId identity2 = new SampleAggregateId(2);

            aggregate = await Repository.GetByIdAsync <SampleAggregate>(identity2).ConfigureAwait(false);

            aggregate.Create();
            await Repository.SaveAsync(aggregate, Guid.NewGuid().ToString(), h => { }).ConfigureAwait(false);

            await Engine.UpdateAndWaitAsync().ConfigureAwait(false);

            var result = sut.GetSlotMetrics();

            Assert.That(result.Count(), Is.EqualTo(2));
            Assert.That(result.ElementAt(0).CommitBehind, Is.EqualTo(0));
            Assert.That(result.ElementAt(0).CommitBehind, Is.EqualTo(0));
        }
예제 #2
0
        public void can_serialize_access_to_the_same_entity()
        {
            //create an aggregate.
            var sampleAggregateId = new SampleAggregateId(1);
            var aggregate         = TestAggregateFactory.Create <SampleAggregate, SampleAggregate.State>(new SampleAggregate.State(), sampleAggregateId);

            aggregate.Create();
            _sut.Save(aggregate, new Guid("135E4E5F-3D65-43AC-9D8D-8A8B0EFF8501"), null);
            NeventStoreExGlobalConfiguration.SetLockThreadSleepCount(100);
            using (var repo1 = CreateRepository())
                using (var repo2 = CreateRepository())
                {
                    aggregate = repo1.GetById <SampleAggregate>(sampleAggregateId);
                    aggregate.Touch();

                    //now create another thread that loads and change the same entity
                    var task = Task <Boolean> .Factory.StartNew(() =>
                    {
                        var aggregate2 = repo2.GetById <SampleAggregate>(sampleAggregateId);
                        aggregate2.Touch();
                        repo2.Save(aggregate2, Guid.NewGuid(), null);
                        return(true);
                    });

                    Thread.Sleep(100);                           //Let be sure the other task is started doing something.
                    repo1.Save(aggregate, Guid.NewGuid(), null); //should not throw
                    Assert.IsTrue(task.Result);                  //inner should not throw.
                }
        }
예제 #3
0
        public void verify_persistence_honor_database_version_when_threshold_passed()
        {
            var sampleAggregateId = new SampleAggregateId(_counter++);
            var aggregate         = TestAggregateFactory.Create <SampleAggregate, SampleAggregate.State>(new SampleAggregate.State(), sampleAggregateId);
            var memento           = new AggregateSnapshot <SampleAggregate.State>()
            {
                Id = sampleAggregateId, Version = 30, State = new SampleAggregate.State()
            };
            var snapshot = new Snapshot("Jarvis", sampleAggregateId, 30, memento);

            _persister.Load(null, 0, null).ReturnsForAnyArgs(snapshot);

            //Simulate the flow of a repository, first operation load the snapshot
            _sut.Load(sampleAggregateId, Int32.MaxValue, typeof(SampleAggregate));

            //then the repository restored the snapshot
            ((ISnapshotable)aggregate).Restore(memento);

            //now iterate
            _persister.DidNotReceiveWithAnyArgs().Persist(null, null);

            for (int i = 0; i < NumberOfCommitsBeforeSnapshot; i++)
            {
                aggregate.Touch();
            }
            _sut.Snapshot(aggregate, "Jarvis", NumberOfCommitsBeforeSnapshot);
            //should be persisted, becauase it is loaded at version 30, but then another snapshotthreshold count of event were raised
            _persister.ReceivedWithAnyArgs().Persist(null, aggregate.GetType().FullName);
        }
        protected void CreateAggregate(Int64 id = 1)
        {
            var aggregateId = new SampleAggregateId(id);
            var aggregate   = TestAggregateFactory.Create <SampleAggregate, SampleAggregate.State>(aggregateId);

            aggregate.Create();
            Repository.Save(aggregate, Guid.NewGuid(), h => { });
        }
예제 #5
0
        protected async Task CreateAggregate(Int64 id = 1)
        {
            var aggregateId = new SampleAggregateId(id);
            var aggregate   = await Repository.GetByIdAsync <SampleAggregate>(aggregateId).ConfigureAwait(false);

            aggregate.Create();
            await Repository.SaveAsync(aggregate, Guid.NewGuid().ToString(), h => { }).ConfigureAwait(false);
        }
예제 #6
0
        public void verify_snapshot_on_new_aggregate_not_call_persistence()
        {
            var sampleAggregateId = new SampleAggregateId(_counter++);
            var aggregate         = TestAggregateFactory.Create <SampleAggregate, SampleAggregate.State>(new SampleAggregate.State(), sampleAggregateId);

            aggregate.Create();
            _sut.Snapshot(aggregate, "Jarvis", 1);
            _persister.DidNotReceiveWithAnyArgs().Persist(null, null);
        }
        public void Verify_equality_base()
        {
            var id1 = new SampleAggregateId(42);
            var id2 = new SampleAggregateId(42);

            Assert.That(id1.Equals(id2));
            Assert.That(id1 == id2);
            Assert.That(object.Equals(id1, id2));
        }
예제 #8
0
        private SimpleTestAtomicReadModel GenerateChangesetWithTwoEvents()
        {
            _aggregateIdSeed++;
            var id  = new SampleAggregateId(_aggregateIdSeed);
            var rm1 = new SimpleTestAtomicReadModel(id);

            rm1.ProcessChangeset(GenerateCreatedEvent(false));
            rm1.ProcessChangeset(GenerateTouchedEvent(false));
            return(rm1);
        }
예제 #9
0
        protected async Task <SampleAggregateId> CreateAggregateAndTouchAsync(Int64 id = 1, Dictionary <String, Object> headers = null)
        {
            var aggregateId = new SampleAggregateId(id);
            var aggregate   = await Repository.GetByIdAsync <SampleAggregate>(aggregateId).ConfigureAwait(false);

            aggregate.Create();
            aggregate.Touch();
            await Repository.SaveAsync(aggregate, Guid.NewGuid().ToString(), h => SetHeaders(h, headers)).ConfigureAwait(false);

            return(aggregateId);
        }
        private async Task <SampleAggregate> CreateAndSaveAggregate()
        {
            var sampleAggregateId = new SampleAggregateId(1);
            var aggregate         = await _repositoryEx.GetByIdAsync <SampleAggregate>(sampleAggregateId).ConfigureAwait(false);

            aggregate.Create();
            aggregate.Touch();
            await _repositoryEx.SaveAsync(aggregate, Guid.NewGuid().ToString(), null).ConfigureAwait(false);

            return(aggregate);
        }
        public async Task Check_tracking_of_aggregate_id()
        {
            var id            = new SampleAggregateId(1);
            var sampleMessage = new SampleAggregateTestCommand(id);
            await _bus.Send(sampleMessage).ConfigureAwait(false);

            _handler.Reset.WaitOne(10000);

            Thread.Sleep(50);
            var track = _messages.AsQueryable().Single();

            Assert.That(track.AggregateId, Is.EqualTo(id.AsString()));
        }
예제 #12
0
        public void can_save_and_load()
        {
            var sampleAggregateId = new SampleAggregateId(1);

            var aggregate = TestAggregateFactory.Create <SampleAggregate, SampleAggregate.State>(new SampleAggregate.State(), sampleAggregateId);

            aggregate.Create();
            _sut.Save(aggregate, new Guid("135E4E5F-3D65-43AC-9D8D-8A8B0EFF8501"), null);

            var loaded = _sut.GetById <SampleAggregate>(sampleAggregateId);

            Assert.IsTrue(loaded.HasBeenCreated);
        }
예제 #13
0
        public void verify_saving_snapshot()
        {
            //create an aggregate.
            var sampleAggregateId = new SampleAggregateId(1);
            var aggregate         = TestAggregateFactory.Create <SampleAggregate, SampleAggregate.State>(new SampleAggregate.State(), sampleAggregateId);

            aggregate.Create();
            for (int i = 0; i < NumberOfCommitsBeforeSnapshot; i++)
            {
                ((IAggregateEx)aggregate).ApplyEvent(new SampleAggregateTouched());
            }
            var events = _sut.Save(aggregate, new Guid("135E4E5F-3D65-43AC-9D8D-8A8B0EFF8501"), null);

            _sut.SnapshotManager.Received().Snapshot(aggregate, "Jarvis", events);
        }
        public void Verify_reverse_translation_is_resilient_to_missing_id()
        {
            TestMapper sut  = new TestMapper(_db, _identityManager);
            String     key1 = Guid.NewGuid().ToString();
            String     key2 = Guid.NewGuid().ToString();

            var id1 = sut.MapWithAutomaticCreate(key1);
            var id2 = sut.MapWithAutomaticCreate(key2);
            var id3 = new SampleAggregateId(100000);

            var reversed = sut.ReverseMap(id1, id2, id3);

            Assert.That(reversed[id1], Is.EqualTo(key1));
            Assert.That(reversed[id2], Is.EqualTo(key2));
            Assert.That(reversed.ContainsKey(id3), Is.False);
        }
        public async Task verify_filtering_for_id_list()
        {
            SampleAggregateId id1 = GenerateId();
            SampleAggregateId id2 = GenerateId();
            SampleAggregateId id3 = GenerateId();

            await SaveAggregateWithHeaders(id1, null).ConfigureAwait(false);
            await SaveAggregateWithHeaders(id2, null).ConfigureAwait(false);
            await SaveAggregateWithHeaders(id3, null).ConfigureAwait(false);

            var returnValue = await sut.GetCommitsAfterCheckpointTokenAsync(0, new List <string>() { id2, id3 }).ConfigureAwait(false);

            Assert.That(returnValue, Has.Count.EqualTo(2), "We have a single commit for the aggregate");
            Assert.That(returnValue.Any(e => e.PartitionId == id2));
            Assert.That(returnValue.Any(e => e.PartitionId == id3));
        }
예제 #16
0
        public void can_save_with_aggregate_identity()
        {
            var sampleAggregateId = new SampleAggregateId(1);
            var aggregate         = TestAggregateFactory.Create <SampleAggregate, SampleAggregate.State>(
                new SampleAggregate.State(),
                sampleAggregateId
                );

            aggregate.Create();
            _sut.Save(aggregate, new Guid("135E4E5F-3D65-43AC-9D8D-8A8B0EFF8501"), null);

            var stream = _eventStore.OpenStream("Jarvis", sampleAggregateId, int.MinValue, int.MaxValue);

            Assert.IsNotNull(stream);
            Assert.AreEqual(1, stream.CommittedEvents.Count);
        }
예제 #17
0
        public void verify_persistence_called_after_threshold_new_aggregate()
        {
            var sampleAggregateId = new SampleAggregateId(_counter++);
            var aggregate         = TestAggregateFactory.Create <SampleAggregate, SampleAggregate.State>(new SampleAggregate.State(), sampleAggregateId);

            aggregate.Create();
            _sut.Snapshot(aggregate, "Jarvis", 1);
            _persister.DidNotReceiveWithAnyArgs().Persist(null, null);

            for (int i = 0; i < NumberOfCommitsBeforeSnapshot; i++)
            {
                aggregate.Touch();
            }
            _sut.Snapshot(aggregate, "Jarvis", NumberOfCommitsBeforeSnapshot);
            //should be persisted because it has more events than snapshotreshold
            _persister.ReceivedWithAnyArgs().Persist(null, aggregate.GetType().FullName);
        }
        private async Task SaveAggregateWithHeaders(SampleAggregateId id, Dictionary <string, string> headers)
        {
            var sampleAggregate = await repository.GetByIdAsync <SampleAggregate>(id).ConfigureAwait(false);

            sampleAggregate.Create();
            sampleAggregate.Touch();

            await repository.SaveAsync(sampleAggregate, Guid.NewGuid().ToString(), a =>
            {
                if (headers != null)
                {
                    foreach (var h in headers)
                    {
                        a.Add(h.Key, h.Value);
                    }
                }
            }).ConfigureAwait(false);
        }
예제 #19
0
        public void profile_snapshot_opt_out()
        {
            var sampleAggregateId = new SampleAggregateId(1);
            var aggregate         = TestAggregateFactory.Create <SampleAggregate, SampleAggregate.State>(new SampleAggregate.State(), sampleAggregateId);

            aggregate.Create();

            _sut.Save(aggregate, Guid.NewGuid(), null);

            int max = 20;

            for (int t = 1; t < max; t++)
            {
                aggregate.Touch();
                _sut.Save(aggregate, Guid.NewGuid(), null);

                if (t == max - 5)
                {
                    var snap = ((ISnapshotable)aggregate).GetSnapshot();
                    _eventStore.Advanced.AddSnapshot(new Snapshot("Jarvis", sampleAggregateId.AsString(), aggregate.Version, snap));
                }
            }

            SnapshotsSettings.OptOut(typeof(SampleAggregate));

            var sw = new Stopwatch();

            sw.Start();
            for (int c = 1; c <= 100; c++)
            {
                using (var repo = new RepositoryEx(
                           _eventStore,
                           _aggregateFactory,
                           new ConflictDetector(),
                           _identityConverter,
                           NSubstitute.Substitute.For <NEventStore.Logging.ILog>()))
                {
                    var loaded = repo.GetById <SampleAggregate>(sampleAggregateId);
                }
            }
            sw.Stop();
            SnapshotsSettings.ClearOptOut();
            Debug.WriteLine("Read time {0} ms", sw.ElapsedMilliseconds);
        }
예제 #20
0
        public void verify_basic_unwinding_with_headers()
        {
            var aggregateId = new SampleAggregateId(1);
            var aggregate   = TestAggregateFactory.Create <SampleAggregate, SampleAggregate.State>(aggregateId);

            aggregate.Create();
            Repository.Save(aggregate, Guid.NewGuid(), h => { h.Add("test.with.dot", "BLAH"); });

            sut.Unwind();

            var allEvents = sut.UnwindedCollection.FindAll();

            Assert.That(allEvents.Count(), Is.EqualTo(1));
            var evt = allEvents.Single();

            Assert.That(evt.EventType, Is.EqualTo("SampleAggregateCreated"));
            Assert.That(evt.GetEvent().AggregateId, Is.EqualTo(aggregateId));
            Assert.That(evt.GetEvent().Context["test.with.dot"], Is.EqualTo("BLAH"));
        }
예제 #21
0
        public async Task verify_basic_unwinding_with_headers()
        {
            var aggregateId = new SampleAggregateId(1);
            var aggregate   = await Repository.GetByIdAsync <SampleAggregate>(aggregateId).ConfigureAwait(false);

            aggregate.Create();
            await Repository.SaveAsync(aggregate, Guid.NewGuid().ToString(), h => h.Add("test.with.dot", "BLAH")).ConfigureAwait(false);

            await sut.UnwindAsync().ConfigureAwait(false);

            var allEvents = sut.UnwindedCollection.FindAll();

            Assert.That(allEvents.Count(), Is.EqualTo(1));
            var evt = allEvents.Single();

            Assert.That(evt.EventType, Is.EqualTo("SampleAggregateCreated"));
            Assert.That((evt.GetEvent() as DomainEvent).AggregateId, Is.EqualTo(aggregateId));
            Assert.That((evt.GetEvent() as DomainEvent).Context["test.with.dot"], Is.EqualTo("BLAH"));
        }
예제 #22
0
        public void can_reuse_repository_with_same_aggregate()
        {
            var sampleAggregateId = new SampleAggregateId(1);
            var aggregate         = TestAggregateFactory.Create <SampleAggregate, SampleAggregate.State>(
                new SampleAggregate.State(),
                sampleAggregateId
                );

            aggregate.Create();
            _sut.Save(aggregate, Guid.NewGuid(), null);

            aggregate.Touch();
            _sut.Save(aggregate, Guid.NewGuid(), null);

            var stream = _eventStore.OpenStream("Jarvis", sampleAggregateId, int.MinValue, int.MaxValue);

            Assert.IsNotNull(stream);
            Assert.AreEqual(2, stream.CommittedEvents.Count);
        }
        public async Task verify_headers_with_null_value()
        {
            SampleAggregateId           id      = GenerateId();
            Dictionary <String, String> headers = new Dictionary <string, string>()
            {
                ["test"]        = "blah",
                ["anothertest"] = null
            };

            await SaveAggregateWithHeaders(id, headers).ConfigureAwait(false);

            var element = await sut.GetCommitsAfterCheckpointTokenAsync(0, new List <string>() { id }).ConfigureAwait(false);

            Assert.That(element, Has.Count.EqualTo(1), "We have a single commit for the aggregate");
            Assert.That(element[0].Id, Is.Not.Null);
            Assert.That(element[0].PartitionId, Is.EqualTo(id.ToString()));
            Assert.That(element[0].Headers.Count, Is.EqualTo(2));
            Assert.That(element[0].Headers["test"], Is.EqualTo("blah"));
            Assert.That(element[0].Headers["anothertest"], Is.EqualTo(null));
        }
예제 #24
0
        public void verify_single_cached_aggregate_repository_tolerance_to_domain_exception()
        {
            var id = new SampleAggregateId(1);

            //First call, everything is ok.
            Int32           stateCount;
            SampleAggregate aggregate;

            using (var repo = _aggregateCachedRepositoryFactory.Create <SampleAggregate>(id))
            {
                aggregate = repo.Aggregate;
                aggregate.Create();
                aggregate.Touch();
                repo.Save(Guid.NewGuid(), updateHeaders => { });
                stateCount = aggregate.InternalState.TouchCount;
            }

            try
            {
                //second call, methdo that throws exception
                using (var repo = _aggregateCachedRepositoryFactory.Create <SampleAggregate>(id))
                {
                    Assert.That(Object.ReferenceEquals(repo.Aggregate, aggregate), "Cache is not working");
                    aggregate = repo.Aggregate;
                    aggregate.Create();
                    aggregate.TouchWithThrow(); //this throws
                    repo.Save(Guid.NewGuid(), updateHeaders => { });
                }
            }
            catch (Exception)
            {
                //Ignore the exception
            }

            //now I want the repository to be fresh with new aggregate
            using (var repo = _aggregateCachedRepositoryFactory.Create <SampleAggregate>(id))
            {
                Assert.That(repo.Aggregate.InternalState.TouchCount, Is.EqualTo(stateCount));
                Assert.That(Object.ReferenceEquals(repo.Aggregate, aggregate), Is.False, "Cache should be invalidated");
            }
        }
예제 #25
0
        public void raise_exception_if_invariants_are_not_satisfied()
        {
            var sampleAggregateId = new SampleAggregateId(1);

            var aggregate = TestAggregateFactory.Create <SampleAggregate, SampleAggregate.State>(new SampleAggregate.State(), sampleAggregateId);

            aggregate.Create();
            aggregate.InvalidateState();
            try
            {
                _sut.Save(aggregate, new Guid("135E4E5F-3D65-43AC-9D8D-8A8B0EFF8501"), null);
                Assert.Fail("We expect an exception");
            }
            catch (InvariantNotSatifiedException ex)
            {
                Assert.That(ex.AggregateId, Is.EqualTo(sampleAggregateId.AsString()));
            }
            catch (Exception ex)
            {
                Assert.Fail("We expect an exception of type InvariantNotSatifiedException but we catched " + ex.GetType().Name);
            }
        }
예제 #26
0
        public void verify_reloading_with_snapshot()
        {
            //create an aggregate.
            var sampleAggregateId = new SampleAggregateId(1);
            var aggregate         = TestAggregateFactory.Create <SampleAggregate, SampleAggregate.State>(new SampleAggregate.State(), sampleAggregateId);

            aggregate.Create();
            for (int i = 0; i < NumberOfCommitsBeforeSnapshot; i++)
            {
                ((IAggregateEx)aggregate).ApplyEvent(new SampleAggregateTouched());
            }
            _sut.SnapshotManager = new CachedSnapshotManager(
                new MongoSnapshotPersisterProvider(_db, NullLogger.Instance),
                new NullSnapshotPersistenceStrategy());
            //this will save the snapshot
            _sut.Save(aggregate, new Guid("135E4E5F-3D65-43AC-9D8D-8A8B0EFF8501"), null);
            var discriminated = BsonSerializer.IsTypeDiscriminated(typeof(AggregateSnapshot <>));

            Console.WriteLine("Discriminated: {0}", discriminated);
            //now reload the aggregate
            var reloaded = _sut.GetById <SampleAggregate>(sampleAggregateId);

            Assert.That(reloaded.SnapshotRestoreVersion, Is.EqualTo(51));
        }