예제 #1
0
        public override void Events_that_cannot_be_deserialized_due_to_unknown_member_do_not_cause_sourcing_to_fail()
        {
            Guid orderId   = Guid.NewGuid();
            var  goodEvent = new Order.CustomerInfoChanged
            {
                CustomerName   = "Waylon Jennings",
                AggregateId    = orderId,
                SequenceNumber = 1
            }.ToStorableEvent();
            var badEvent = new StorableEvent
            {
                StreamName     = goodEvent.StreamName,
                Type           = goodEvent.Type,
                AggregateId    = goodEvent.AggregateId,
                SequenceNumber = 2,
                Body           = new
                {
                    CustomerName = "Willie Nelson",
                    HairColor    = "red"
                }.ToJson(),
                UtcTime = DateTime.UtcNow
            };

            SaveEventsDirectly(goodEvent, badEvent);

            var repository = CreateRepository <Order>();

            var order = repository.GetLatest(orderId);

            order.CustomerName.Should().Be("Willie Nelson");
        }
        public async Task A_DuckTypeProjector_can_access_the_metadata_of_unknown_event_types_dynamically()
        {
            StorableEvent storableEvent = null;

            using (var db = EventStoreDbContext())
            {
                storableEvent = new StorableEvent
                {
                    AggregateId = Guid.NewGuid(),
                    StreamName  = Any.CamelCaseName(),
                    Type        = Any.CamelCaseName(),
                    Body        = new { }.ToJson()
                };
                db.Events.Add(storableEvent);
                await db.SaveChangesAsync();
            }

            IEvent receivedEvent = null;

            var projector = Projector.CreateFor <dynamic>(e => receivedEvent = e);

            using (var catchup = CreateReadModelCatchup(projector))
            {
                await catchup.Run();
            }

            long absoluteSequenceNumber = ((IHaveExtensibleMetada)receivedEvent).Metadata.AbsoluteSequenceNumber;

            absoluteSequenceNumber.Should().Be(storableEvent.Id);
        }
 public static InMemoryStoredEvent ToInMemoryStoredEvent(this StorableEvent e) =>
 new InMemoryStoredEvent
 {
     SequenceNumber = e.SequenceNumber,
     AggregateId    = e.AggregateId.ToString(),
     Timestamp      = e.Timestamp,
     Type           = e.Type,
     Body           = e.Body,
     ETag           = e.ETag,
     StreamName     = e.StreamName
 };
예제 #4
0
        public void UtcTime_setter_accurately_converts_values_forwarded_to_TimeStamp_setter()
        {
            var now = DateTime.UtcNow;

            var e = new StorableEvent
            {
                UtcTime = now
            };

            e.Timestamp.Should().Be(now);
        }
예제 #5
0
        public void UtcTime_getter_accurately_converts_values_set_via_TimeStamp_setter()
        {
            var now = DateTime.UtcNow;

            var e = new StorableEvent
            {
                Timestamp = now
            };

            e.UtcTime.Should().Be(now);
        }
예제 #6
0
        /// <summary>
        /// Creates an in-memory stored event from the specified <see cref="StorableEvent" />.
        /// </summary>
        /// <param name="e">The event from which to create an in-memory stored event.</param>
        public static InMemoryStoredEvent ToInMemoryStoredEvent(this StorableEvent e)
        {
            var @event = new InMemoryStoredEvent
            {
                SequenceNumber = e.SequenceNumber,
                AggregateId    = e.AggregateId.ToString(),
                Timestamp      = e.Timestamp,
                Type           = e.Type,
                Body           = e.Body,
                ETag           = e.ETag,
                StreamName     = e.StreamName
            };

            @event.Metadata.AbsoluteSequenceNumber = e.Id;
            return(@event);
        }
예제 #7
0
        public void Repository_will_not_try_to_source_events_from_a_different_aggregate_type()
        {
            Guid id = Guid.NewGuid();
            var  e  = new StorableEvent
            {
                AggregateId = id,
                Type        = "SomeEventType",
                StreamName  = "SomeAggregateType",
                Body        = new { Something = Any.Words() }.ToJson()
            };

            SaveEventsDirectly(e);

            var repository = CreateRepository <Order>();

            var order = repository.GetLatest(id);

            order.Should().BeNull();
        }
        public async Task ReadModelCatchup_does_not_query_events_that_no_subscribed_projector_is_interested_in()
        {
            Events.Write(100, _ => Events.Any());
            Events.Write(1, _ => new Order.Created());

            var projector2 = Projector.Create <CustomerAccount.Created>(e => { });

            StorableEvent extraneousEvent = null;

            using (var catchup = CreateReadModelCatchup(projector2))
                using (var eventStore = EventStoreDbContext())
                {
                    var eventsQueried = 0;
                    catchup.Progress
                    .Where(s => !s.IsStartOfBatch)
                    .ForEachAsync(s =>
                    {
                        var eventId = s.CurrentEventId;
                        var @event  = eventStore.Events.Single(e => e.Id == eventId);
                        if (@event.StreamName != "CustomerAccount" || @event.Type != "Created")
                        {
                            extraneousEvent = @event;
                            catchup.Dispose();
                        }
                        eventsQueried++;
                    });
                    await catchup.Run()
                    .ContinueWith(r => catchup.Dispose());

                    Console.WriteLine(new { eventsQueried });
                }

            if (extraneousEvent != null)
            {
                Assert.Fail(string.Format("Found an event that should not have been queried from the event store: {0}:{1} (#{2})",
                                          extraneousEvent.StreamName,
                                          extraneousEvent.Type,
                                          extraneousEvent.Id));
            }
        }
예제 #9
0
        public async Task Events_that_cannot_be_deserialized_to_the_expected_type_are_logged_as_EventHandlingErrors()
        {
            var badEvent = new StorableEvent
            {
                Actor      = Any.Email(),
                StreamName = typeof(Order).Name,
                Type       = typeof(Order.ItemAdded).Name,
                Body       = new { Price = "oops this is not a number" }.ToJson(),
                SequenceNumber = Any.PositiveInt(),
                AggregateId    = Any.Guid(),
                UtcTime        = DateTime.UtcNow
            };

            using (var eventStore = EventStoreDbContext())
            {
                eventStore.Events.Add(badEvent);
                await eventStore.SaveChangesAsync();
            }

            using (var catchup = CreateReadModelCatchup(new Projector1()))
            {
                await catchup.Run();
            }

            using (var readModels = ReadModelDbContext())
            {
                var failure = readModels.Set <EventHandlingError>()
                              .OrderByDescending(e => e.Id)
                              .First(e => e.AggregateId == badEvent.AggregateId);
                failure.Error.Should().Contain("JsonReaderException");
                failure.SerializedEvent.Should().Contain(badEvent.Body);
                failure.Actor.Should().Be(badEvent.Actor);
                failure.OriginalId.Should().Be(badEvent.Id);
                failure.AggregateId.Should().Be(badEvent.AggregateId);
                failure.SequenceNumber.Should().Be(badEvent.SequenceNumber);
                failure.StreamName.Should().Be(badEvent.StreamName);
                failure.EventTypeName.Should().Be(badEvent.Type);
            }
        }