예제 #1
0
        public void Storing_event_source_should_succeed()
        {
            var targetStore      = new MsSqlServerEventStore(connectionString);
            var theEventSourceId = Guid.NewGuid();
            var theCommitId      = Guid.NewGuid();

            var eventStream = Prepare.Events(
                new CustomerCreatedEvent("Foo", 35),
                new CustomerNameChanged("Name" + 2),
                new CustomerNameChanged("Name" + 3),
                new CustomerNameChanged("Name" + 4))
                              .ForSourceUncomitted(theEventSourceId, theCommitId);

            targetStore.Store(eventStream);

            var eventsFromStore = targetStore.ReadFrom(theEventSourceId, long.MinValue, long.MaxValue);

            eventsFromStore.Count().Should().Be(eventStream.Count());

            for (int i = 0; i < eventsFromStore.Count(); i++)
            {
                var uncommittedEvent = eventStream.ElementAt(i);
                var committedEvent   = eventsFromStore.ElementAt(i);

                committedEvent.EventSourceId.Should().Be(uncommittedEvent.EventSourceId);
                committedEvent.EventIdentifier.Should().Be(uncommittedEvent.EventIdentifier);
                committedEvent.EventSequence.Should().Be(uncommittedEvent.EventSequence);
                committedEvent.Payload.GetType().Should().Be(uncommittedEvent.Payload.GetType());
            }
        }
예제 #2
0
        public void Saving_with_concurrent_event_adds_should_not_be_causing_deadlocks()
        {
            // test created in response to an issue with high frequency adds causing deadlocks on the EventSource table.
            // I reworked the sequencing of reads/updates to the EventSource table to reduce the amount
            // of time to any locks will be held. But this wasn't strictly required as the problem resided
            // in the fact that there was no index on the event source table result in full table scans occuring.
            // I therefore also changed the DDL to incude an non clustered index on EventSource.Id which resulted
            // in a nice performance boost during informal testing.

            var targetStore = new MsSqlServerEventStore(connectionString);

            var tasks = new Task[30]; // this number require to reproduce the issue might vary depending on hardware

            for (int idx = 0; idx < tasks.Length; idx++)
            {
                tasks[idx] = Task.Factory.StartNew(() =>
                {
                    var theEventSourceId = Guid.NewGuid();
                    var theCommitId      = Guid.NewGuid();

                    var eventStream = Prepare.Events(new CustomerCreatedEvent(Task.CurrentId.ToString(), 35))
                                      .ForSourceUncomitted(theEventSourceId, theCommitId);

                    // should not be receiving a deadlock
                    targetStore.Store(eventStream);
                });
            }

            Task.WaitAll(tasks);
        }
        public void it_should_throw_a_concurrency_exception()
        {
            var eventStream = Prepare.Events(new AccountTitleChangedEvent("Title"))
                              .ForSourceUncomitted(EventSourceId, Guid.NewGuid());

            EventStore.Store(eventStream);
        }
예제 #4
0
 protected override IEnumerable <SourcedEvent> Given()
 {
     return(Prepare.Events
            (
                new NewProjectCreated(TheId, OldName, "myproject")
            )
            .ForSource(TheId));
 }
예제 #5
0
        public void it_should_throw_a_concurrency_exception()
        {
            var eventStream = Prepare.Events(new AccountTitleChangedEvent("Title"))
                              .ForSourceUncomitted(EventSourceId, Guid.NewGuid());

            ConcurrencyException ex = Assert.Throws <ConcurrencyException>(() => EventStore.Store(eventStream));

            Assert.NotNull(ex);
        }
예제 #6
0
 protected override IEnumerable <SourcedEvent> Given()
 {
     return(Prepare.Events
            (
                new NewProjectCreated(TheProjectId, "My Project", "myproject"),
                new MemberAddedToProject(TheMemberId)
            )
            .ForSource(TheProjectId));
 }
예제 #7
0
        public void Loading_it_from_history_should_apply_all_events()
        {
            var aggId        = Guid.NewGuid();
            var stream       = Prepare.Events(new HandledEvent(), new HandledEvent(), new HandledEvent()).ForSource(aggId);
            var theAggregate = new MyAggregateRoot(aggId);

            theAggregate.InitializeFromHistory(stream);

            theAggregate.FooEventHandlerInvokeCount.Should().Be(3);
        }
예제 #8
0
        public void Init_should_set_From_and_To_version_information()
        {
            var sourceId        = Guid.NewGuid();
            var eventObjects    = new[] { new Object(), new Object(), new Object() };
            var committedEvents = Prepare.Events(eventObjects).ForSource(sourceId, 5).ToList();

            var sut = new CommittedEventStream(sourceId, committedEvents);

            sut.FromVersion.Should().Be(committedEvents.First().EventSequence);
            sut.ToVersion.Should().Be(committedEvents.Last().EventSequence);
        }
예제 #9
0
        public void Saving_with_concurrent_event_edits_should_be_subject_to_concurrency_checks()
        {
            // test created in response to an issue with concurrent edits happening within the window between
            // reading the current version number of the aggregate and the event source record being updated with
            // the new version number. this would leave the event stream for an event source out of sequence and
            // the aggregate in a state in which it could not be retrieved :o
            var concurrencyExceptionThrown = false;

            var targetStore = new MsSqlServerEventStore(connectionString);

            var theEventSourceId = Guid.NewGuid();
            var theCommitId      = Guid.NewGuid();

            // make sure that the event source for the aggregate is created
            var creationEvent = Prepare.Events(new CustomerCreatedEvent("Foo", 35))
                                .ForSourceUncomitted(theEventSourceId, theCommitId);

            targetStore.Store(creationEvent);

            var tasks = new Task[130];

            // now simulate concurreny updates coming in on the same aggregate
            for (int idx = 0; idx < tasks.Length; idx++)
            {
                tasks[idx] = Task.Factory.StartNew(() =>
                {
                    var changeEvent = new CustomerNameChanged(DateTime.Now.Ticks.ToString())
                    {
                        CustomerId = theEventSourceId
                    };
                    var eventStream = Prepare.Events(changeEvent)
                                      .ForSourceUncomitted(theEventSourceId, Guid.NewGuid(), 2);

                    try
                    {
                        targetStore.Store(eventStream);
                    }
                    catch (ConcurrencyException)
                    {
                        concurrencyExceptionThrown = true;
                    }

                    targetStore.ReadFrom(theEventSourceId, long.MinValue, long.MaxValue);
                });
            }

            Task.WaitAll(tasks);

            if (concurrencyExceptionThrown == false)
            {
                Assert.True(false, "We're expecting concurrency exceptions!");
            }
        }
예제 #10
0
        public NoDBEventStoreTestFixture()
        {
            EventStore    = new NoDBEventStore("./NoDBTests/" + GetType().Name);
            EventSourceId = Guid.NewGuid();
            Guid entityId = Guid.NewGuid();

            Events = new object[] { new AccountTitleChangedEvent("Title") };
            var eventStream = Prepare.Events(Events)
                              .ForSourceUncomitted(EventSourceId, Guid.NewGuid());

            EventStore.Store(eventStream);
        }
예제 #11
0
        public void It_could_not_be_loaded_from_history_when_it_already_contains_uncommitted_events()
        {
            var theAggregate = new MyAggregateRoot();

            theAggregate.MethodThatCausesAnEventThatHasAHandler();
            theAggregate.MethodThatCausesAnEventThatHasAHandler();

            var stream = Prepare.Events(new HandledEvent(), new HandledEvent()).ForSource(theAggregate.EventSourceId);

            Action act = () => theAggregate.InitializeFromHistory(stream);

            act.ShouldThrow <InvalidOperationException>();
        }
예제 #12
0
        public void Storing_empty_event_stream_should_not_throw()
        {
            var targetStore      = new MsSqlServerEventStore(connectionString);
            var theEventSourceId = Guid.NewGuid();
            var theCommitId      = Guid.NewGuid();

            var eventStream = Prepare.Events(new object[0])
                              .ForSourceUncomitted(theEventSourceId, theCommitId);

            targetStore.Store(eventStream);

            Assert.True(true);
        }
예제 #13
0
        public void When_constructing_it_with_events_where_one_has_an_incorrect_event_source_id_it_should_throw_argument_exception()
        {
            var sourceId        = Guid.NewGuid();
            var eventObjects    = new[] { new Object(), new Object(), new Object() };
            var committedEvents = Prepare.Events(eventObjects).ForSource(sourceId).ToList();

            var lastEvent         = committedEvents.Last();
            var incorrectSourceId = Guid.NewGuid();
            var incorrectEvent    = new CommittedEvent(lastEvent.CommitId, lastEvent.EventIdentifier, incorrectSourceId, lastEvent.EventSequence, lastEvent.EventTimeStamp, lastEvent.Payload, lastEvent.EventVersion);

            committedEvents[committedEvents.Count - 1] = incorrectEvent;

            Action act = () => new CommittedEventStream(sourceId, committedEvents);

            act.ShouldThrow <ArgumentException>();
        }
예제 #14
0
        public void Storing_entity_sourced_event_should_preserve_entity_id()
        {
            var targetStore      = new MsSqlServerEventStore(connectionString);
            var theEventSourceId = Guid.NewGuid();
            var theCommitId      = Guid.NewGuid();

            var theEntityId = Guid.NewGuid();
            var eventStream = Prepare.Events(new AccountNameChangedEvent(theEntityId, "NewName"))
                              .ForSourceUncomitted(theEventSourceId, theCommitId);

            targetStore.Store(eventStream);

            var restoredEvent = targetStore.ReadFrom(theEventSourceId, long.MinValue, long.MaxValue).Single();

            var payload = (AccountNameChangedEvent)restoredEvent.Payload;

            payload.EntityId.Should().Be(theEntityId);
        }
예제 #15
0
        public void Saving_snapshot_should_not_throw_an_exception_when_snapshot_is_valid()
        {
            var targetStore = new MsSqlServerEventStore(connectionString);

            var anId      = Guid.NewGuid();
            var aCommitId = Guid.NewGuid();
            var aVersion  = 12;

            var eventStream = Prepare.Events(new object())
                              .ForSourceUncomitted(anId, aCommitId);
            var snapshot = new Snapshot(anId, aVersion, new MySnapshot());


            targetStore.Store(eventStream);
            targetStore.SaveSnapshot(snapshot);

            var savedSnapshot = targetStore.GetSnapshot(anId, long.MaxValue);

            savedSnapshot.EventSourceId.Should().Be(anId);
            savedSnapshot.Version.Should().Be(aVersion);
        }