public void Projection_write_speed_without_unit_of_work()
        {
            var eventsRead = 0;

            var projector1 = Projector.Create <IEvent>(e =>
            {
                using (var db = new ReadModelDbContext())
                {
                    db.Set <ProductInventory>().Add(new ProductInventory
                    {
                        ProductName      = Guid.NewGuid().ToString(),
                        QuantityInStock  = Any.Int(1, 5),
                        QuantityReserved = 0
                    });

                    db.SaveChanges();

                    eventsRead++;
                }
            }).Named(MethodBase.GetCurrentMethod().Name + ":projector1");

            using (var catchup = new ReadModelCatchup(projector1)
            {
                StartAtEventId = startAtEventId
            })
            {
                catchup.Run();
            }

            Console.WriteLine(new { eventsRead });

            // TODO: (Write_speed_without_unit_of_work) write test
            Assert.Fail("Test not written yet.");
        }
        public void Projection_write_speed_with_unit_of_work()
        {
            var eventsRead = 0;

            var projector1 = Projector.Create <IEvent>(e =>
            {
                using (var update = this.Update())
                {
                    var db = update.Resource <ReadModelDbContext>();

                    db.Set <ProductInventory>().Add(new ProductInventory
                    {
                        ProductName      = Guid.NewGuid().ToString(),
                        QuantityInStock  = Any.Int(1, 5),
                        QuantityReserved = 0
                    });

                    db.SaveChanges();

                    eventsRead++;
                }
            }).Named(MethodBase.GetCurrentMethod().Name + ":projector1");

            using (var catchup = new ReadModelCatchup(
                       eventStoreDbContext: () => EventStoreDbContext(),
                       readModelDbContext: () => ReadModelDbContext(),
                       startAtEventId: startAtEventId, projectors: projector1))
            {
                catchup.Run();
            }

            Console.WriteLine(new { eventsRead });
        }
Exemple #3
0
        public ReadModelCatchup CreateReadModelCatchup(
            Expression <Func <StorableEvent, bool> > filter = null,
            int batchSize       = 10000,
            long?startAtEventId = null,
            params object[] projectors)
        {
            startAtEventId = startAtEventId ??
                             HighestEventId + 1;

            var catchupName = CatchupName(projectors, startAtEventId);

            var catchup = new ReadModelCatchup(
                eventStoreDbContext: () => EventStoreDbContext(),
                readModelDbContext: () => ReadModelDbContext(),
                startAtEventId: startAtEventId.Value,
                projectors: projectors,
                batchSize: batchSize,
                filter: filter)
            {
                Name = catchupName
            };

            Configuration.Current.RegisterForDisposal(catchup);
            return(catchup);
        }
        /// <summary>
        /// Configures the system to use SQL-backed command scheduling.
        /// </summary>
        /// <param name="configuration">The configuration.</param>
        /// <returns>The updated configuration.</returns>
        public static Configuration UseSqlCommandScheduling(
            this Configuration configuration,
            Action<ReadModelCatchup<CommandSchedulerDbContext>> configureCatchup = null)
        {
            var container = configuration.Container;
            var scheduler = container.Resolve<SqlCommandScheduler>();
            var subscription = container.Resolve<IEventBus>().Subscribe(scheduler);
            configuration.RegisterForDisposal(subscription);
            container.RegisterSingle(c => scheduler);

            if (configureCatchup != null)
            {
                var catchup = new ReadModelCatchup<CommandSchedulerDbContext>(scheduler)
                {
                    CreateReadModelDbContext = scheduler.CreateCommandSchedulerDbContext
                };
                configureCatchup(catchup);
                catchup.PollEventStore();
                container.RegisterSingle(c => catchup);
                configuration.RegisterForDisposal(catchup);
            }

            configuration.UsesSqlCommandScheduling(true);

            return configuration;
        }
        public virtual CatchupWrapper CreateReadModelCatchup(params object[] projectors)
        {
            var startAtEventId = HighestEventId + 1;
            var catchup        = new ReadModelCatchup(projectors)
            {
                StartAtEventId = startAtEventId,
                Name           = "from " + startAtEventId
            };

            disposables.Add(catchup);
            return(new CatchupWrapper <ReadModelDbContext>(catchup));
        }
        public void Read_speed_for_IEvent()
        {
            var eventsRead = 0;

            var projector1 = Projector.Create<IEvent>(e => { eventsRead++; }).Named(MethodBase.GetCurrentMethod().Name + ":projector1");

            using (var catchup = new ReadModelCatchup(projector1) { StartAtEventId = startAtEventId })
            {
                catchup.Run();
            }

            Console.WriteLine(new { eventsRead });
        }
Exemple #7
0
        public ReadModelCatchup CreateReadModelCatchup(params object[] projectors)
        {
            var catchup = new ReadModelCatchup(
                eventStoreDbContext: () => EventStoreDbContext(),
                readModelDbContext: () => ReadModelDbContext(),
                startAtEventId: HighestEventId + 1,
                projectors: projectors)
            {
                Name = $"from {HighestEventId + 1}"
            };

            Configuration.Current.RegisterForDisposal(catchup);
            return(catchup);
        }
        public void Read_speed_for_two_specific_events()
        {
            var eventsRead = 0;

            var projector1 = Projector.Create<Order.ItemAdded>(e => { eventsRead++; }).Named(MethodBase.GetCurrentMethod().Name + ":projector1");
            var projector2 = Projector.Create<CustomerAccount.RequestedNoSpam>(e => { eventsRead++; }).Named(MethodBase.GetCurrentMethod().Name + ":projector2");

            using (var catchup = new ReadModelCatchup(projector1, projector2) { StartAtEventId = startAtEventId })
            {
                catchup.Run();
            }

            Console.WriteLine(new { eventsRead });
        }
Exemple #9
0
        public ReadModelCatchup CreateReadModelCatchup(params object[] projectors)
        {
            var catchup = new ReadModelCatchup(
                eventStoreDbContext: () => EventStoreDbContext(),
                readModelDbContext: () => ReadModelDbContext(),
                startAtEventId: HighestEventId + 1,
                projectors: projectors)
            {
                Name = "from " + (HighestEventId + 1)
            };

            disposables.Add(catchup);
            return(catchup);
        }
        public void Read_speed_for_IEvent()
        {
            var eventsRead = 0;

            var projector1 = Projector.Create<IEvent>(e => { eventsRead++; }).Named(MethodBase.GetCurrentMethod().Name + ":projector1");

            using (var catchup = new ReadModelCatchup(
                eventStoreDbContext: () => EventStoreDbContext(),
                readModelDbContext: () => ReadModelDbContext(),
                startAtEventId: startAtEventId, projectors: projector1))
            {
                catchup.Run();
            }

            Console.WriteLine(new { eventsRead });
        }
        public void Read_speed_for_IEvent()
        {
            var eventsRead = 0;

            var projector1 = Projector.Create <IEvent>(e => { eventsRead++; }).Named(MethodBase.GetCurrentMethod().Name + ":projector1");

            using (var catchup = new ReadModelCatchup(projector1)
            {
                StartAtEventId = startAtEventId
            })
            {
                catchup.Run();
            }

            Console.WriteLine(new { eventsRead });
        }
        public void Read_speed_for_IEvent()
        {
            var eventsRead = 0;

            var projector1 = Projector.Create <IEvent>(e => { eventsRead++; }).Named(MethodBase.GetCurrentMethod().Name + ":projector1");

            using (var catchup = new ReadModelCatchup(
                       eventStoreDbContext: () => EventStoreDbContext(),
                       readModelDbContext: () => ReadModelDbContext(),
                       startAtEventId: startAtEventId, projectors: projector1))
            {
                catchup.Run();
            }

            Console.WriteLine(new { eventsRead });
        }
Exemple #13
0
        public ReadModelCatchup CreateReadModelCatchup(
            object[] projectors,
            Func <EventStoreDbContext> eventStoreDbContext,
            Func <ReadModelDbContext> readModelDbContext = null)
        {
            var catchup = new ReadModelCatchup(
                eventStoreDbContext: eventStoreDbContext,
                readModelDbContext: readModelDbContext ?? (() => ReadModelDbContext()),
                startAtEventId: HighestEventId + 1,
                projectors: projectors)
            {
                Name = $"from {HighestEventId + 1}"
            };

            Configuration.Current.RegisterForDisposal(catchup);
            return(catchup);
        }
        public void Read_speed_for_two_specific_events()
        {
            var eventsRead = 0;

            var projector1 = Projector.Create <Order.ItemAdded>(e => { eventsRead++; }).Named(MethodBase.GetCurrentMethod().Name + ":projector1");
            var projector2 = Projector.Create <CustomerAccount.RequestedNoSpam>(e => { eventsRead++; }).Named(MethodBase.GetCurrentMethod().Name + ":projector2");

            using (var catchup = new ReadModelCatchup(projector1, projector2)
            {
                StartAtEventId = startAtEventId
            })
            {
                catchup.Run();
            }

            Console.WriteLine(new { eventsRead });
        }
Exemple #15
0
        public ReadModelCatchup <T> CreateReadModelCatchup <T>(
            Func <EventStoreDbContext> eventStoreDbContext,
            params object[] projectors)
            where T : DbContext, new()
        {
            var catchup = new ReadModelCatchup <T>(
                eventStoreDbContext: eventStoreDbContext,
                readModelDbContext: () => new T(),
                startAtEventId: HighestEventId + 1,
                projectors: projectors)
            {
                Name = "from " + (HighestEventId + 1)
            };

            disposables.Add(catchup);
            return(catchup);
        }
Exemple #16
0
        public ReadModelCatchup <T> CreateReadModelCatchup <T>(
            Func <EventStoreDbContext> eventStoreDbContext,
            params object[] projectors)
            where T : DbContext, new()
        {
            var catchup = new ReadModelCatchup <T>(
                eventStoreDbContext: eventStoreDbContext,
                readModelDbContext: () => new T(),
                startAtEventId: HighestEventId + 1,
                projectors: projectors)
            {
                Name = $"from {HighestEventId + 1}"
            };

            Configuration.Current.RegisterForDisposal(catchup);
            return(catchup);
        }
        public void Read_speed_for_two_specific_events()
        {
            var eventsRead = 0;

            var projector1 = Projector.Create <Order.ItemAdded>(e => { eventsRead++; }).Named(MethodBase.GetCurrentMethod().Name + ":projector1");
            var projector2 = Projector.Create <CustomerAccount.RequestedNoSpam>(e => { eventsRead++; }).Named(MethodBase.GetCurrentMethod().Name + ":projector2");

            using (var catchup = new ReadModelCatchup(
                       eventStoreDbContext: () => EventStoreDbContext(),
                       readModelDbContext: () => ReadModelDbContext(),
                       startAtEventId: startAtEventId,
                       projectors: new object[] { projector1, projector2 }))
            {
                catchup.Run();
            }

            Console.WriteLine(new { eventsRead });
        }
Exemple #18
0
        public void ReadModelCatchup_StartAtEventId_can_be_used_to_avoid_requery_of_previous_events()
        {
            var lastEventId = Events.Write(50, _ => Events.Any());

            var eventsProjected = 0;

            var projector = Projector.Create <Event>(e => { eventsProjected++; }).Named(MethodBase.GetCurrentMethod().Name);

            using (var catchup = new ReadModelCatchup(projector)
            {
                StartAtEventId = lastEventId - 20
            })
            {
                catchup.Run();
            }

            eventsProjected.Should().Be(21);
        }
Exemple #19
0
        public async Task ReadModelCatchup_StartAtEventId_can_be_used_to_avoid_requery_of_previous_events()
        {
            var lastEventId = Events.Write(50, _ => Events.Any());

            var eventsProjected = 0;

            var projector = Projector.Create <Event>(e => { eventsProjected++; })
                            .Named(MethodBase.GetCurrentMethod().Name);

            using (var catchup = new ReadModelCatchup(
                       eventStoreDbContext: () => EventStoreDbContext(),
                       readModelDbContext: () => ReadModelDbContext(),
                       startAtEventId: lastEventId - 20,
                       projectors: projector))
            {
                await catchup.Run();
            }

            eventsProjected.Should().Be(21);
        }
        /// <summary>
        /// Configures the system to use SQL-backed command scheduling.
        /// </summary>
        /// <param name="configuration">The configuration.</param>
        /// <returns>The updated configuration.</returns>
        public static Configuration UseSqlCommandScheduling(
            this Configuration configuration,
            Action<ReadModelCatchup<CommandSchedulerDbContext>> configureCatchup = null)
        {
            var container = configuration.Container;

            container.AddFallbackToDefaultClock();

            var scheduler = new SqlCommandScheduler(
                configuration,
                container.Resolve<Func<CommandSchedulerDbContext>>(),
                container.Resolve<GetClockName>());

            if (container.All(r => r.Key != typeof (SqlCommandScheduler)))
            {
                container.Register(c => scheduler)
                         .Register<ISchedulerClockTrigger>(c => scheduler)
                         .Register<ISchedulerClockRepository>(c => scheduler);
            }

            var subscription = container.Resolve<IEventBus>().Subscribe(scheduler);
            configuration.RegisterForDisposal(subscription);
            container.RegisterSingle(c => scheduler);

            if (configureCatchup != null)
            {
                var catchup = new ReadModelCatchup<CommandSchedulerDbContext>(scheduler)
                {
                    CreateReadModelDbContext = scheduler.CreateCommandSchedulerDbContext
                };
                configureCatchup(catchup);
                catchup.PollEventStore();
                container.RegisterSingle(c => catchup);
                configuration.RegisterForDisposal(catchup);
            }

            configuration.IsUsingSqlCommandScheduling(true);

            return configuration;
        }
Exemple #21
0
        private void RunCatchup()
        {
            // TODO: (RunCatchup) provide trace output here and throughout
            var projectors = handlers.OrEmpty()
                             .Where(h => h.GetType().IsProjectorType())
                             .ToArray();

            if (!projectors.Any())
            {
                return;
            }

            if (configuration.IsUsingSqlEventStore())
            {
                var catchup = new ReadModelCatchup(projectors)
                {
                    CreateEventStoreDbContext = CreateEventStoreDbContext,
                    CreateReadModelDbContext  = CreateReadModelDbContext,
                    StartAtEventId            = startCatchupAtEventId
                };

                using (catchup)
                    using (catchup.EventBus.Errors.Subscribe(scenario.AddEventHandlingError))
                        using (catchup.Progress.Subscribe(s => Console.WriteLine(s)))
                        {
                            catchup.Run();
                        }
            }
            else
            {
                EventBus.PublishAsync(InitialEvents.ToArray()).Wait();
            }

            if (scenario.EventHandlingErrors.Any())
            {
                throw new ScenarioSetupException(
                          "The following event handling errors occurred during projection catchup: " +
                          string.Join("\n", scenario.EventHandlingErrors.Select(e => e.Exception.ToString())));
            }
        }
Exemple #22
0
        public async Task Two_different_projectors_can_catch_up_to_two_different_event_stores_using_separate_catchups()
        {
            // arrange
            var projector1CallCount = 0;
            var projector2CallCount = 0;
            var projector1          = Projector.Create <Order.ItemAdded>(e => projector1CallCount++).Named(MethodBase.GetCurrentMethod().Name + "1");
            var projector2          = Projector.Create <Order.ItemAdded>(e => projector2CallCount++).Named(MethodBase.GetCurrentMethod().Name + "2");
            var startProjector2AtId = new OtherEventStoreDbContext().DisposeAfter(db => db.HighestEventId()) + 1;

            Events.Write(5, createEventStore: () => EventStoreDbContext());
            Events.Write(5, createEventStore: () => new OtherEventStoreDbContext());

            using (var eventStoreCatchup = new ReadModelCatchup(
                       readModelDbContext: () => ReadModelDbContext(),
                       eventStoreDbContext: () => EventStoreDbContext(),
                       startAtEventId: HighestEventId + 1,
                       projectors: projector1)
            {
                Name = "eventStoreCatchup"
            })
                using (var otherEventStoreCatchup = new ReadModelCatchup(
                           readModelDbContext: () => ReadModelDbContext(),
                           eventStoreDbContext: () => new OtherEventStoreDbContext(),
                           startAtEventId: startProjector2AtId,
                           projectors: projector2)
                {
                    Name = "otherEventStoreCatchup"
                })
                {
                    // act
                    await eventStoreCatchup.SingleBatchAsync();

                    await otherEventStoreCatchup.SingleBatchAsync();
                }

            // assert
            projector1CallCount.Should().Be(5, "projector1 should get all events from event stream");
            projector2CallCount.Should().Be(5, "projector2 should get all events from event stream");
        }
Exemple #23
0
        private void RunCatchup()
        {
            var projectors = handlers.OrEmpty()
                             .Where(h => h.GetType().IsProjectorType())
                             .ToArray();

            if (!projectors.Any())
            {
                return;
            }

            if (configuration.IsUsingSqlEventStore())
            {
                var catchup = new ReadModelCatchup(
                    eventStoreDbContext: () => configuration.EventStoreDbContext(),
                    readModelDbContext: () => configuration.ReadModelDbContext(),
                    startAtEventId: startCatchupAtEventId,
                    projectors: projectors);

                using (catchup)
                    using (catchup.EventBus.Errors.Subscribe(scenario.AddEventHandlingError))
                        using (catchup.Progress.Subscribe(s => Console.WriteLine(s)))
                        {
                            catchup.Run().Wait(TimeSpan.FromSeconds(30));
                        }
            }
            else
            {
                EventBus.PublishAsync(InitialEvents.ToArray()).Wait();
            }

            if (scenario.EventHandlingErrors.Any())
            {
                throw new ScenarioSetupException(
                          "The following event handling errors occurred during projection catchup: " +
                          string.Join("\n", scenario.EventHandlingErrors.Select(e => e.Exception.ToString())));
            }
        }
        public void Projection_write_speed_without_unit_of_work()
        {
            var eventsRead = 0;

            var projector1 = Projector.Create<IEvent>(e =>
            {
                using (var db = new ReadModelDbContext())
                {
                    db.Set<ProductInventory>().Add(new ProductInventory
                    {
                        ProductName = Guid.NewGuid().ToString(),
                        QuantityInStock = Any.Int(1, 5),
                        QuantityReserved = 0
                    });

                    db.SaveChanges();

                    eventsRead++;
                }
            }).Named(MethodBase.GetCurrentMethod().Name + ":projector1");

            using (var catchup = new ReadModelCatchup(projector1) { StartAtEventId = startAtEventId })
            {
                catchup.Run();
            }

            Console.WriteLine(new { eventsRead });

            // TODO: (Write_speed_without_unit_of_work) write test
            Assert.Fail("Test not written yet.");
        }
        public void Projection_write_speed_with_unit_of_work()
        {
            var eventsRead = 0;

            var projector1 = Projector.Create<IEvent>(e =>
            {
                using (var update = this.Update())
                {
                    var db = update.Resource<ReadModelDbContext>();

                    db.Set<ProductInventory>().Add(new ProductInventory
                    {
                        ProductName = Guid.NewGuid().ToString(),
                        QuantityInStock = Any.Int(1, 5),
                        QuantityReserved = 0
                    });

                    db.SaveChanges();

                    eventsRead++;
                }
            }).Named(MethodBase.GetCurrentMethod().Name + ":projector1");

            using (var catchup = new ReadModelCatchup(
                eventStoreDbContext: () => EventStoreDbContext(),
                readModelDbContext: () => ReadModelDbContext(),
                startAtEventId: startAtEventId, projectors: projector1))
            {
                catchup.Run();
            }

            Console.WriteLine(new { eventsRead });
        }
        public void Read_speed_for_two_specific_events()
        {
            var eventsRead = 0;

            var projector1 = Projector.Create<Order.ItemAdded>(e => { eventsRead++; }).Named(MethodBase.GetCurrentMethod().Name + ":projector1");
            var projector2 = Projector.Create<CustomerAccount.RequestedNoSpam>(e => { eventsRead++; }).Named(MethodBase.GetCurrentMethod().Name + ":projector2");

            using (var catchup = new ReadModelCatchup(
                eventStoreDbContext: () => EventStoreDbContext(),
                readModelDbContext: () => ReadModelDbContext(),
                startAtEventId: startAtEventId,
                projectors: new object[] { projector1, projector2 }))
            {
                catchup.Run();
            }

            Console.WriteLine(new { eventsRead });
        }