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 async Task Report_projections_can_be_created_using_anonymous_projectors_over_multiple_event_types()
        {
            var projector = Projector.Combine(
                Projector.CreateFor <Placed>(e =>
            {
                using (var db1 = ReadModelDbContext())
                {
                    db1.OrderTallyByStatus(OrderTally.OrderStatus.Pending).Count++;
                    db1.SaveChanges();
                }
            }),
                Projector.CreateFor <Cancelled>(e =>
            {
                using (var db2 = ReadModelDbContext())
                {
                    db2.OrderTallyByStatus(OrderTally.OrderStatus.Canceled).Count++;
                    db2.OrderTallyByStatus(OrderTally.OrderStatus.Pending).Count--;
                    db2.SaveChanges();
                }
            }),
                Projector.CreateFor <Delivered>(e =>
            {
                using (var db3 = ReadModelDbContext())
                {
                    db3.OrderTallyByStatus(OrderTally.OrderStatus.Delivered).Count++;
                    db3.OrderTallyByStatus(OrderTally.OrderStatus.Pending).Count--;
                    db3.SaveChanges();
                }
            })).Named("Order status report");

            Events.Write(20, _ => new Order.Cancelled());
            Events.Write(20, _ => new Order.Delivered());
            Events.Write(50, _ => new Order.Placed());

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

            using (var db = ReadModelDbContext())
            {
                db.Set <OrderTally>()
                .Single(t => t.Status == "Canceled")
                .Count
                .Should()
                .Be(20);
                db.Set <OrderTally>()
                .Single(t => t.Status == "Delivered")
                .Count
                .Should()
                .Be(20);
                db.Set <OrderTally>()
                .Single(t => t.Status == "Pending")
                .Count
                .Should()
                .Be(10);
            }
        }
        public async Task When_classes_not_implementing_IEvent_are_used_to_query_the_event_store_then_only_the_corresponding_events_are_queried()
        {
            var eventsQueried         = 0;
            var expectedEventsQueried = 0;

            Events.Write(20, _ =>
            {
                Event e = null;
                switch (Any.Int(1, 3))
                {
                case 1:
                    e = (Event)Events.Any();
                    break;

                case 2:
                    e = new Order.ItemAdded();
                    break;

                case 3:
                    e = new Order.ItemRemoved();
                    break;
                }

                if (e is Order.ItemAdded || e is Order.ItemRemoved)
                {
                    expectedEventsQueried++;
                }

                e.AggregateId = Guid.NewGuid();

                return(e);
            });

            var projector1 = Projector.CreateFor <ItemAdded>(e =>
            {
                eventsQueried++;
            });
            var projector2 = Projector.CreateFor <ItemRemoved>(e =>
            {
                eventsQueried++;
            });

            using (var catchup = CreateReadModelCatchup(projector1, projector2))
            {
                await catchup.Run();
            }

            eventsQueried.Should().Be(expectedEventsQueried);
        }
        public async Task When_classes_not_implementing_IEvent_are_used_to_query_the_event_store_then_non_nested_classes_have_their_EventStreamName_set_correctly()
        {
            Events.Write(1, _ => new Order.Cancelled());
            Cancelled cancelled = null;
            var       projector = Projector.CreateFor <Cancelled>(e =>
            {
                cancelled = e;
            });

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

            cancelled.EventStreamName.Should().Be("Order");
        }
        public async Task A_DuckTypeProjector_can_access_the_metadata_of_known_event_types_dynamically()
        {
            var lastEventId = Events.Write(1, _ => new Order.CustomerInfoChanged());

            Order.CustomerInfoChanged receivedEvent = null;

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

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

            long absoluteSequenceNumber = receivedEvent.Metadata.AbsoluteSequenceNumber;

            absoluteSequenceNumber.Should().Be(lastEventId);
        }
        public async Task Duck_projectors_can_access_the_event_properties_of_received_events()
        {
            var expectedTimestamp       = DateTimeOffset.Parse("2014-07-03");
            var expectedAggregateId     = Any.Guid();
            var receivedAggregateId     = new Guid();
            var expectedSequenceNumber  = Any.PositiveInt();
            int receivedSequenceNumber  = 0;
            var receivedTimestamp       = new DateTimeOffset();
            var receivedEventStreamName = "";
            var receivedEventTypeName   = "";

            using (var db = EventStoreDbContext())
            {
                db.Events.Add(new StorableEvent
                {
                    AggregateId    = expectedAggregateId,
                    SequenceNumber = expectedSequenceNumber,
                    Timestamp      = expectedTimestamp,
                    StreamName     = "Reporting",
                    Type           = "DuckEvent",
                    Body           = new { Quacks = 9000 }.ToJson()
                });

                await db.SaveChangesAsync();
            }

            var projector = Projector.CreateFor <Reporting.DuckEvent>(e =>
            {
                receivedAggregateId     = e.AggregateId;
                receivedSequenceNumber  = e.SequenceNumber;
                receivedTimestamp       = e.Timestamp;
                receivedEventStreamName = e.EventStreamName;
                receivedEventTypeName   = e.EventTypeName;
            });

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

            receivedAggregateId.Should().Be(expectedAggregateId);
            receivedSequenceNumber.Should().Be(expectedSequenceNumber);
            receivedTimestamp.Should().Be(expectedTimestamp);
            receivedEventStreamName.Should().Be("Reporting");
            receivedEventTypeName.Should().Be("DuckEvent");
        }
        public async Task When_classes_not_implementing_IEvent_are_used_to_query_the_event_store_then_nested_classes_can_be_used_to_specify_stream_names()
        {
            using (var db = EventStoreDbContext())
            {
                Enumerable.Range(1, 5).ForEach(i => db.Events.Add(new StorableEvent
                {
                    AggregateId = Guid.NewGuid(),
                    StreamName  = "Reporting",
                    Type        = "DuckEvent",
                    Body        = new { Quacks = i }.ToJson()
                }));

                Enumerable.Range(1, 5).ForEach(i => db.Events.Add(new StorableEvent
                {
                    AggregateId = Guid.NewGuid(),
                    StreamName  = Any.CamelCaseName(),
                    Type        = "DuckEvent",
                    Body        = new { Quacks = i }.ToJson()
                }));

                await db.SaveChangesAsync();
            }
            var unNestedDucks = 0;
            var nestedDucks   = 0;

            var projector1 = Projector.CreateFor <DuckEvent>(e =>
            {
                unNestedDucks++;
            });
            var projector2 = Projector.CreateFor <Reporting.DuckEvent>(e =>
            {
                nestedDucks++;
            });

            using (var catchup = CreateReadModelCatchup(projector1, projector2))
            {
                await catchup.Run();
            }

            nestedDucks.Should().Be(5);
            unNestedDucks.Should().Be(10);
        }
예제 #8
0
        public void When_classes_not_implementing_IEvent_are_used_to_query_the_event_store_then_properties_are_duck_deserialized()
        {
            using (var db = new EventStoreDbContext())
            {
                Enumerable.Range(1, 5).ForEach(i => db.Events.Add(new StorableEvent
                {
                    AggregateId = Guid.NewGuid(),
                    StreamName  = "Reporting",
                    Type        = "DuckEvent",
                    Body        = new { Quacks = i }.ToJson()
                }));

                Enumerable.Range(1, 5).ForEach(i => db.Events.Add(new StorableEvent
                {
                    AggregateId = Guid.NewGuid(),
                    StreamName  = Any.CamelCaseName(),
                    Type        = "DuckEvent",
                    Body        = new { Quacks = i }.ToJson()
                }));

                db.SaveChanges();
            }
            var unNestedDuckQuacks = 0;
            var nestedDuckQuacks   = 0;

            var projector1 = Projector.CreateFor <DuckEvent>(e =>
            {
                unNestedDuckQuacks += e.Quacks;
            });
            var projector2 = Projector.CreateFor <Reporting.DuckEvent>(e =>
            {
                nestedDuckQuacks += e.Quacks;
            });

            using (var catchup = CreateReadModelCatchup(projector1, projector2))
            {
                catchup.Run();
            }

            nestedDuckQuacks.Should().Be(15);
            unNestedDuckQuacks.Should().Be(30);
        }
예제 #9
0
        public async Task Catchup_continues_when_DuckTypeProjector_throws()
        {
            Events.Write(20);
            int counter       = 0;
            int eventsHandled = 0;
            var handler       = Projector.CreateFor <ItemAdded>(e =>
            {
                counter++;
                if (counter == 10)
                {
                    throw new Exception("oops!");
                }
                eventsHandled++;
            });

            await new ReadModelCatchup(handler)
            {
                StartAtEventId = HighestEventId + 1
            }.SingleBatchAsync();

            eventsHandled.Should().Be(19);
        }
예제 #10
0
        public async Task Catchup_continues_when_DuckTypeProjector_throws()
        {
            Events.Write(20);
            var counter       = 0;
            var eventsHandled = 0;
            var handler       = Projector.CreateFor <ItemAdded>(e =>
            {
                counter++;
                if (counter == 10)
                {
                    throw new Exception("oops!");
                }
                eventsHandled++;
            });

            await new ReadModelCatchup(
                eventStoreDbContext: () => EventStoreDbContext(),
                readModelDbContext: () => ReadModelDbContext(),
                startAtEventId: HighestEventId + 1,
                projectors: handler).SingleBatchAsync();

            eventsHandled.Should().Be(19);
        }