Beispiel #1
0
        public async Task GetLatest_can_return_an_aggregate_built_from_a_snapshot()
        {
            // arrange
            var snapshotRepository = new InMemorySnapshotRepository();

            Configuration.Current.UseDependency <ISnapshotRepository>(_ => snapshotRepository);

            var original = new CustomerAccount()
                           .Apply(new ChangeEmailAddress(Any.Email()))
                           .Apply(new RequestNoSpam());
            var repository = CreateRepository <CustomerAccount>();
            await repository.Save(original);

            await snapshotRepository.SaveSnapshot(original);

            // act
            var fromSnapshot = await repository.GetLatest(original.Id);

            // assert
            fromSnapshot.Id.Should().Be(original.Id);
            fromSnapshot.Version.Should().Be(fromSnapshot.Version);
            fromSnapshot.EmailAddress.Should().Be(fromSnapshot.EmailAddress);
            fromSnapshot.UserName.Should().Be(fromSnapshot.UserName);
            fromSnapshot.NoSpam.Should().Be(fromSnapshot.NoSpam);
        }
        public async Task GetLatest_can_return_an_aggregate_built_from_a_snapshot_projection()
        {
            // arrange
            var snapshotRepository = new InMemorySnapshotRepository();

            Configuration.Current.UseDependency <ISnapshotRepository>(_ => snapshotRepository);

            var snapshot = new CustomerAccountSnapshot
            {
                AggregateId       = Any.Guid(),
                Version           = 123,
                AggregateTypeName = AggregateType <CustomerAccount> .EventStreamName,
                EmailAddress      = Any.Email(),
                NoSpam            = true,
                UserName          = Any.FullName(),
                ETags             = new[] { Any.Word(), Any.Word() }
            };
            await snapshotRepository.SaveSnapshot(snapshot);

            // act
            var account = await CreateRepository <CustomerAccount>().GetLatest(snapshot.AggregateId);

            // assert
            account.Id.Should().Be(snapshot.AggregateId);
            account.Version.Should().Be(snapshot.Version);
            account.EmailAddress.Should().Be(snapshot.EmailAddress);
            account.UserName.Should().Be(snapshot.UserName);
            account.NoSpam.Should().Be(snapshot.NoSpam);

            foreach (var etag in snapshot.ETags)
            {
                account.HasETag(etag).Should().BeTrue("etags are expected to be loaded from the snapshot");
            }
        }
Beispiel #3
0
        public async Task GetLatest_can_return_an_aggregate_built_from_a_snapshot_projection()
        {
            // arrange
            var snapshotRepository = new InMemorySnapshotRepository();

            Configuration.Current.UseDependency <ISnapshotRepository>(_ => snapshotRepository);

            var etags       = new[] { Any.Word(), Any.Word() };
            var bloomFilter = new BloomFilter();

            etags.ForEach(bloomFilter.Add);

            var snapshot = new CustomerAccountSnapshot
            {
                AggregateId       = Any.Guid(),
                Version           = 123,
                AggregateTypeName = AggregateType <CustomerAccount> .EventStreamName,
                EmailAddress      = Any.Email(),
                NoSpam            = true,
                UserName          = Any.FullName(),
                ETags             = bloomFilter
            };
            await snapshotRepository.SaveSnapshot(snapshot);

            // act
            var account = await CreateRepository <CustomerAccount>().GetLatest(snapshot.AggregateId);

            // assert
            account.Id.Should().Be(snapshot.AggregateId);
            account.Version.Should().Be(snapshot.Version);
            account.EmailAddress.Should().Be(snapshot.EmailAddress);
            account.UserName.Should().Be(snapshot.UserName);
            account.NoSpam.Should().Be(snapshot.NoSpam);
        }
        public async Task Snapshotting_can_be_bypassed()
        {
            var snapshotRepository = new InMemorySnapshotRepository();

            Configuration.Current.UseDependency <ISnapshotRepository>(_ => snapshotRepository);

            var account = new CustomerAccount()
                          .Apply(new ChangeEmailAddress(Any.Email()))
                          .Apply(new RequestSpam())
                          .Apply(new SendMarketingEmail())
                          .Apply(new SendOrderConfirmationEmail(Any.AlphanumericString(8, 8)));

            var eventSourcedRepository = CreateRepository <CustomerAccount>();
            await eventSourcedRepository.Save(account);

            await snapshotRepository.SaveSnapshot(account);

            // act
            account = await eventSourcedRepository.GetLatest(account.Id);

            // assert
            account.Events().Count()
            .Should()
            .Be(4);
        }
Beispiel #5
0
        public async Task Null_or_empty_or_whitespace_ETags_are_not_saved_in_the_snapshot()
        {
            var account = new CustomerAccount()
                          .Apply(new RequestSpam
            {
                ETag = ""
            })
                          .Apply(new RequestSpam
            {
                ETag = "      "
            })
                          .Apply(new RequestSpam
            {
                ETag = null
            });

            var repository = new InMemorySnapshotRepository();
            await repository.SaveSnapshot(account);

            var snapshot = await repository.GetSnapshot(account.Id);

            snapshot.ETags
            .Should()
            .BeEmpty();
        }
        public async Task When_new_events_are_added_to_an_aggregate_sourced_from_a_stale_snapshot_the_version_increments_correctly()
        {
            // arrange
            var snapshotRepository = new InMemorySnapshotRepository();

            Configuration.Current.UseDependency <ISnapshotRepository>(_ => snapshotRepository);

            var snapshot = new CustomerAccountSnapshot
            {
                AggregateId       = Any.Guid(),
                Version           = 122,
                AggregateTypeName = AggregateType <CustomerAccount> .EventStreamName,
                EmailAddress      = Any.Email(),
                NoSpam            = true,
                UserName          = Any.FullName(),
                ETags             = new[] { Any.Word(), Any.Word() }
            };

            await snapshotRepository.SaveSnapshot(snapshot);

            await SaveEventsDirectly(new CustomerAccount.RequestedSpam
            {
                AggregateId    = snapshot.AggregateId,
                SequenceNumber = snapshot.Version + 1
            }.ToStoredEvent());

            // act
            var account = await CreateRepository <CustomerAccount>().GetLatest(snapshot.AggregateId);

            account.Apply(new RequestSpam());

            // assert
            account.Version.Should().Be(124);
        }
        public async Task When_a_snapshot_is_not_up_to_date_then_GetLatest_retrieves_later_events_and_applies_them()
        {
            // arrange
            var snapshotRepository = new InMemorySnapshotRepository();

            Configuration.Current.UseDependency <ISnapshotRepository>(_ => snapshotRepository);

            var snapshot = new CustomerAccountSnapshot
            {
                AggregateId       = Any.Guid(),
                Version           = 123,
                AggregateTypeName = AggregateType <CustomerAccount> .EventStreamName,
                EmailAddress      = Any.Email(),
                NoSpam            = true,
                UserName          = Any.FullName(),
                ETags             = new[] { Any.Word(), Any.Word() }
            };
            await snapshotRepository.SaveSnapshot(snapshot);

            await SaveEventsDirectly(new CustomerAccount.RequestedSpam
            {
                AggregateId    = snapshot.AggregateId,
                SequenceNumber = 124
            }.ToStoredEvent());

            // act
            var account = await CreateRepository <CustomerAccount>().GetLatest(snapshot.AggregateId);

            // assert
            account.Version.Should().Be(124);
            account.NoSpam.Should().Be(false);
        }
        public async Task Null_or_empty_or_whitespace_ETags_are_not_saved_in_the_snapshot()
        {
            var account = new CustomerAccount()
                .Apply(new RequestSpam
                       {
                           ETag = ""
                       })
                .Apply(new RequestSpam
                       {
                           ETag = "      "
                       })
                .Apply(new RequestSpam
                       {
                           ETag = null
                       });

            var repository = new InMemorySnapshotRepository();
            await repository.SaveSnapshot(account);

            var snapshot = await repository.GetSnapshot(account.Id);

            snapshot.ETags
                    .Should()
                    .BeEmpty();
        }
Beispiel #9
0
        public async Task When_a_snapshot_is_not_up_to_date_then_GetLatest_retrieves_later_events_and_applies_them()
        {
            // arrange
            var snapshotRepository = new InMemorySnapshotRepository();

            Configuration.Current.UseDependency <ISnapshotRepository>(_ => snapshotRepository);

            var customerAccount = new CustomerAccount()
                                  .Apply(new ChangeEmailAddress(Any.Email()));

            var repository = CreateRepository <CustomerAccount>();

            await repository.Save(customerAccount);

            var snapshot = customerAccount.CreateSnapshot();

            Console.WriteLine(snapshot.Body);

            await snapshotRepository.SaveSnapshot(snapshot);

            await SaveEventsDirectly(new CustomerAccount.RequestedSpam
            {
                AggregateId    = snapshot.AggregateId,
                SequenceNumber = 124
            }.ToInMemoryStoredEvent());

            // act
            var account = await repository.GetLatest(snapshot.AggregateId);

            // assert
            account.Version.Should().Be(124);
            account.NoSpam.Should().Be(false);
        }
Beispiel #10
0
        public async Task When_new_events_are_added_to_an_aggregate_sourced_from_a_stale_snapshot_the_version_increments_correctly()
        {
            // arrange
            var snapshotRepository = new InMemorySnapshotRepository();

            Configuration.Current.UseDependency <ISnapshotRepository>(_ => snapshotRepository);

            var account = new CustomerAccount()
                          .Apply(new ChangeEmailAddress(Any.Email()))
                          .Apply(new RequestSpam());
            var originalVersion = account.Version;
            var repository      = CreateRepository <CustomerAccount>();
            await repository.Save(account);

            await snapshotRepository.SaveSnapshot(account);

            await SaveEventsDirectly(new CustomerAccount.RequestedSpam
            {
                AggregateId    = account.Id,
                SequenceNumber = originalVersion + 1
            }.ToInMemoryStoredEvent());

            // act
            account = await repository.GetLatest(account.Id);

            // assert
            account.Version.Should().Be(originalVersion + 1);
        }
Beispiel #11
0
        public void SaveSnapshot_throws_an_informative_exception_when_no_snapshot_creator_is_found()
        {
            var repository = new InMemorySnapshotRepository();

            Action save = () => repository.SaveSnapshot(new Order(new CreateOrder(Any.FullName()))).Wait();

            save.ShouldThrow <DomainConfigurationException>();
        }
        public void SaveSnapshot_throws_an_informative_exception_when_no_snapshot_creator_is_found()
        {
            var repository = new InMemorySnapshotRepository();

            Action save = () => repository.SaveSnapshot(new Order(new CreateOrder(Any.FullName()))).Wait();

            save.ShouldThrow<DomainConfigurationException>();
        }
Beispiel #13
0
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);

            var container = new Container();

            DependencyResolver.SetResolver(new SmDependencyResolver(container));

            //
            // Service bus
            //
            var bus = ServiceBus.Run(c => c
                                     .SetServiceLocator(new StructureMapServiceLocator(container))
                                     .MemorySynchronousTransport()
                                     .SetName("Main  Service Bus")
                                     .SetInputQueue("sync.server")
                                     .AddEndpoint(type => type.FullName.EndsWith("Event"), "sync.server")
                                     .AddEndpoint(type => type.FullName.EndsWith("Command"), "sync.server")
                                     .AddEndpoint(type => type.FullName.EndsWith("Message"), "sync.server")
                                     .Dispatcher(d => d
                                                 .AddHandlers(typeof(UserAR).Assembly)
                                                 .AddHandlers(typeof(UserEntityEventHandler).Assembly)
                                                 )
                                     );

            container.Configure(config => config.For <IServiceBus>().Singleton().Use(bus));

            //
            // Domain and Event store configuration
            //
            var dataTypeRegistry = new AssemblyQualifiedDataTypeRegistry();


            var transitionsRepository = new InMemoryTransitionRepository();

            var transitionsStorage = new TransitionStorage(transitionsRepository);
            var snapshotRepository = new InMemorySnapshotRepository();

            container.Configure(config =>
            {
                config.For <ITransitionRepository>().Singleton().Use(transitionsRepository);
                config.For <ITransitionStorage>().Singleton().Use(transitionsStorage);
                config.For <CqrsSample.Infrastructure.Snapshots.ISnapshotRepository>().Singleton().Use(snapshotRepository);
                config.For <IDataTypeRegistry>().Singleton().Use(dataTypeRegistry);
                config.For <IEventStore>().Use <EventStore>();
                config.For <IEventBus>().Use <ParalectServiceBusEventBus>();
                config.For <IRepository>().Use <Repository>();
                config.For <ICommandService>().Use <CommandService>();
            });
        }
Beispiel #14
0
        static async Task Main(string[] args)
        {
            var eventRepository    = new InMemoryEventRepository();
            var snapshotRepository = new InMemorySnapshotRepository();
            var solution           = new Solution(eventRepository, snapshotRepository);

            solution.AddContext <EntityContext>();
            solution.AddContext <AttributeContext>();


            await solution.ExecuteCommand(new CreateEntity(Guid.NewGuid(), "Name1"));

            await solution.ExecuteCommand(new CreateEntity(Guid.NewGuid(), "Name2"));

            await solution.ExecuteCommand(new CreateEntity(Guid.NewGuid(), "Name2"));
        }
        public async Task ETags_are_saved_in_the_snapshot()
        {
            var etag = Any.Guid().ToString();
            var account = new CustomerAccount().Apply(new RequestSpam
                                                      {
                                                          ETag = etag
                                                      });
            account.ConfirmSave();

            var repository = new InMemorySnapshotRepository();
            await repository.SaveSnapshot(account);

            var snapshot = await repository.GetSnapshot(account.Id);

            snapshot.ETags
                    .Should()
                    .Contain(etag);
        }
Beispiel #16
0
        public async Task ETags_are_saved_in_the_snapshot()
        {
            var etag    = Any.Guid().ToString();
            var account = new CustomerAccount().Apply(new RequestSpam
            {
                ETag = etag
            });

            account.ConfirmSave();

            var repository = new InMemorySnapshotRepository();
            await repository.SaveSnapshot(account);

            var snapshot = await repository.GetSnapshot(account.Id);

            snapshot.ETags
            .Should()
            .Contain(etag);
        }
Beispiel #17
0
        public async Task Repeated_ETags_are_not_repeated_in_the_snapshot()
        {
            var account = new CustomerAccount()
                          .Apply(new RequestSpam
            {
                ETag = "a"
            })
                          .Apply(new RequestSpam
            {
                ETag = "a"
            });

            account.ConfirmSave();

            var repository = new InMemorySnapshotRepository();
            await repository.SaveSnapshot(account);

            var snapshot = await repository.GetSnapshot(account.Id);

            snapshot.ETags
            .Should()
            .ContainSingle(etag => etag == "a");
        }
Beispiel #18
0
        public async Task When_new_events_are_added_to_an_aggregate_sourced_from_a_fully_current_snapshot_the_version_increments_correctly()
        {
            // arrange
            var snapshotRepository = new InMemorySnapshotRepository();

            Configuration.Current.UseDependency <ISnapshotRepository>(_ => snapshotRepository);

            var customerAccount = new CustomerAccount()
                                  .Apply(new ChangeEmailAddress(Any.Email()));
            var repository = CreateRepository <CustomerAccount>();
            await repository.Save(customerAccount);

            var snapshottedVersion = customerAccount.Version;

            await snapshotRepository.SaveSnapshot(customerAccount);

            // act
            var account = await repository.GetLatest(customerAccount.Id);

            account.Apply(new RequestSpam());

            // assert
            account.Version.Should().Be(snapshottedVersion + 1);
        }
        public async Task Repeated_ETags_are_not_repeated_in_the_snapshot()
        {
            var account = new CustomerAccount()
                .Apply(new RequestSpam
                       {
                           ETag = "a"
                       })
                .Apply(new RequestSpam
                       {
                           ETag = "a"
                       });
            account.ConfirmSave();

            var repository = new InMemorySnapshotRepository();
            await repository.SaveSnapshot(account);

            var snapshot = await repository.GetSnapshot(account.Id);

            snapshot.ETags
                    .Should()
                    .ContainSingle(etag => etag == "a");
        }