public async Task Scatter_gather_produces_a_unique_etag_per_sent_command()
        {
            var repo = configuration.Repository<MarcoPoloPlayerWhoIsIt>();
            var it = new MarcoPoloPlayerWhoIsIt();
            await repo.Save(it);

            var numberOfPlayers = 6;
            var players = Enumerable.Range(1, numberOfPlayers)
                                    .Select(_ => new MarcoPoloPlayerWhoIsNotIt());

            foreach (var player in players)
            {
                var joinGame = new MarcoPoloPlayerWhoIsNotIt.JoinGame
                {
                    IdOfPlayerWhoIsIt = it.Id
                };
                await player.ApplyAsync(joinGame).AndSave();
            }

            await repo.Refresh(it);

            await it.ApplyAsync(new MarcoPoloPlayerWhoIsIt.SayMarco()).AndSave();

            await repo.Refresh(it);

            it.Events()
              .OfType<MarcoPoloPlayerWhoIsIt.HeardPolo>()
              .Count()
              .Should()
              .Be(numberOfPlayers);
        }
        public async Task Aggregates_can_schedule_commands_against_themselves_idempotently()
        {
            var it = new MarcoPoloPlayerWhoIsIt();
            await Save(it);

            await it.ApplyAsync(new MarcoPoloPlayerWhoIsIt.KeepSayingMarcoOverAndOver());

            VirtualClock.Current.AdvanceBy(TimeSpan.FromMinutes(1));

            it = await Get<MarcoPoloPlayerWhoIsIt>(it.Id);

            it.Events()
                .OfType<MarcoPoloPlayerWhoIsIt.SaidMarco>()
                .Count()
                .Should()
                .BeGreaterOrEqualTo(5);
        }
        public async Task Multiple_scheduled_commands_having_the_some_causative_command_etag_have_repeatable_and_unique_etags()
        {
            var scheduled = new List<ICommand>();
            string[] firstPassEtags;
            string[] secondPassEtags;

            configuration.AddToCommandSchedulerPipeline<MarcoPoloPlayerWhoIsIt>(async (cmd, next) =>
            {
                scheduled.Add(cmd.Command);
                await next(cmd);
            });
            configuration.AddToCommandSchedulerPipeline<MarcoPoloPlayerWhoIsNotIt>(async (cmd, next) =>
            {
                scheduled.Add(cmd.Command);
                await next(cmd);
            });

            var it = new MarcoPoloPlayerWhoIsIt()
                .Apply(new MarcoPoloPlayerWhoIsIt.AddPlayer { PlayerId = Any.Guid() })
                .Apply(new MarcoPoloPlayerWhoIsIt.AddPlayer { PlayerId = Any.Guid() });
            Console.WriteLine("[Saving]");
            await itRepo.Save(it);

            var sourceEtag = Any.Guid().ToString();

            await it.ApplyAsync(new MarcoPoloPlayerWhoIsIt.KeepSayingMarcoOverAndOver
            {
                ETag = sourceEtag
            });
//            VirtualClock.Current.AdvanceBy(TimeSpan.FromSeconds(2));
            firstPassEtags = scheduled.Select(c => c.ETag).ToArray();
            Console.WriteLine(new { firstPassEtags }.ToLogString());

            scheduled.Clear();

            // revert the aggregate and do the same thing again
            it = await itRepo.GetLatest(it.Id);
            await it.ApplyAsync(new MarcoPoloPlayerWhoIsIt.KeepSayingMarcoOverAndOver
            {
                ETag = sourceEtag
            });

            Console.WriteLine("about to advance clock for the second time");

//            VirtualClock.Current.AdvanceBy(TimeSpan.FromSeconds(2));
            secondPassEtags = scheduled.Select(c => c.ETag).ToArray();
            Console.WriteLine(new { secondPassEtags }.ToLogString());

            secondPassEtags.Should()
                           .Equal(firstPassEtags);
        }
        public async Task Multiple_scheduled_commands_having_the_some_causative_command_etag_have_repeatable_and_unique_etags()
        {
            var scheduled = new List<ICommand>();
            var configuration = Configuration.Current;
            configuration.AddToCommandSchedulerPipeline<MarcoPoloPlayerWhoIsIt>(async (cmd, next) =>
            {
                scheduled.Add(cmd.Command);
                await next(cmd);
            });
            configuration.AddToCommandSchedulerPipeline<MarcoPoloPlayerWhoIsNotIt>(async (cmd, next) =>
            {
                scheduled.Add(cmd.Command);
                await next(cmd);
            });

            var it = new MarcoPoloPlayerWhoIsIt()
                .Apply(new MarcoPoloPlayerWhoIsIt.AddPlayer { PlayerId = Any.Guid() })
                .Apply(new MarcoPoloPlayerWhoIsIt.AddPlayer { PlayerId = Any.Guid() });

            await Save(it);

            var sourceEtag = Any.Guid().ToString();

            await it.ApplyAsync(new MarcoPoloPlayerWhoIsIt.KeepSayingMarcoOverAndOver
            {
                ETag = sourceEtag
            });
            var firstPassEtags = scheduled.Select(c => c.ETag).ToArray();

            scheduled.Clear();

            // revert the aggregate and do the same thing again
            it = await Get<MarcoPoloPlayerWhoIsIt>(it.Id);
            await it.ApplyAsync(new MarcoPoloPlayerWhoIsIt.KeepSayingMarcoOverAndOver
            {
                ETag = sourceEtag
            });

            var secondPassEtags = scheduled.Select(c => c.ETag).ToArray();

            secondPassEtags.Should()
                .Equal(firstPassEtags);
        }