コード例 #1
0
        public async Task <object> RunAsync(ExpectEventsScenario scenario, CancellationToken ct = default)
        {
            var checkpoint = await WriteGivens(scenario.Givens);

            var exception = await Catch.Exception(() => _resolver(scenario.When)(scenario.When, ct));

            if (exception != null)
            {
                return(scenario.ButThrewException(exception));
            }

            var recordedEvents = await ReadThens(checkpoint);

            var config = new ComparisonConfig
            {
                MaxDifferences = int.MaxValue,
                MaxStructDepth = 5
            };
            var comparer       = new CompareLogic(config);
            var expectedEvents = Array.ConvertAll(scenario.Thens,
                                                  then => new RecordedEvent(_converter(new StreamName(then.Stream)), then.Event));
            var result = comparer.Compare(expectedEvents, recordedEvents);

            if (result.AreEqual)
            {
                return(scenario.Pass());
            }
            return(scenario.ButRecordedOtherEvents(recordedEvents));
        }
コード例 #2
0
 public static CommandHandlerDispatcher Using(CommandHandlerResolver resolver)
 {
     if (resolver == null)
     {
         throw new ArgumentNullException(nameof(resolver));
     }
     return((message, cancellationToken) => resolver(message)(message, cancellationToken));
 }
コード例 #3
0
        private static void Main()
        {
            var resolver = new CommandHandlerResolver(new CommandModule());
            var settings = new CommandHandlingSettings(
                resolver,
                new CommandMediaTypeMap(new CommandMediaTypeWithQualifierVersionFormatter()));
            var commandHandlingMiddleware = CommandHandlingMiddleware.HandleCommands(settings);

            using(WebApp.Start("http://*****:*****@"..\..\wwwroot")
                    });
                    app.UseStaticFiles(new StaticFileOptions
                    {
                        RequestPath = new PathString("/cedarjs"),
                        FileSystem = new PhysicalFileSystem(@"..\..\..\Cedar.HttpCommandHandling.Js")
                    });
                    app.Map("/test/commands", commandsApp => commandsApp.Use(commandHandlingMiddleware));
                }))
            {
                Process.Start("http://localhost:8080/index.html");
                Console.WriteLine("Press any key to exit");
                Console.ReadKey();
            }
        }
コード例 #4
0
        static void Main()
        {
            Func<IFoo> getFoo = () => new DummyFoo();
            var module = new CommandModule(getFoo);
            var resolver = new CommandHandlerResolver(module);
            var commandMediaTypeMap = new CommandMediaTypeMap(new CommandMediaTypeWithQualifierVersionFormatter())
            {
                // Use a string to decouple command name from the command clr type. This will ensure 
                // refactoring, i.e. moving CommandThatHasASyncHandler or renaming it, won't change your http API. 
                { "CommandThatHasASyncHandler", typeof(CommandThatHasASyncHandler) }, 

                // Can use typeof().Name if you are not concerned with backwards compat or versioning.
                { typeof(CommandThatHasAnAsyncHandler).Name, typeof(CommandThatHasAnAsyncHandler) },
            };
            var settings = new CommandHandlingSettings(resolver, commandMediaTypeMap);
            var commandHandlingMiddleware = CommandHandlingMiddleware.HandleCommands(settings);

            // 5. Add the middleware to your owin pipeline
            using(WebApp.Start("http://localhost:8080",
                app =>
                {
                    app.Use(commandHandlingMiddleware);
                }))
            {
                Console.WriteLine("Press any key");
            }
        }
コード例 #5
0
        private static void Main()
        {
            var resolver = new CommandHandlerResolver(new CommandModule());
            var settings = new CommandHandlingSettings(resolver);
            var commandHandlingMiddleware = CommandHandlingMiddleware.HandleCommands(settings);

            using (WebApp.Start("http://*****:*****@"..\..\wwwroot")
                });
                app.UseStaticFiles(new StaticFileOptions
                {
                    RequestPath = new PathString("/cedarjs"),
                    FileSystem = new PhysicalFileSystem(@"..\..\..\Cedar.HttpCommandHandling.Js")
                });
                app.Map("/test/commands", commandsApp => commandsApp.Use(commandHandlingMiddleware));
            }))
            {
                Process.Start("http://localhost:8080/index.html");
                Console.WriteLine("Press any key to exit");
                Console.ReadKey();
            }
        }
コード例 #6
0
        private static void Main()
        {
            var resolver = new CommandHandlerResolver(new CommandModule());

            var commandMediaTypeMap = new CommandMediaTypeMap(new CommandMediaTypeWithQualifierVersionFormatter())
            {
                { typeof(CommandThatIsAccepted).Name, typeof(CommandThatIsAccepted) },
                { typeof(CommandThatThrowsProblemDetailsException).Name, typeof(CommandThatThrowsProblemDetailsException) }
            };

            var settings = new CommandHandlingSettings(resolver, commandMediaTypeMap);

            var commandHandlingMiddleware = CommandHandlingMiddleware.HandleCommands(settings);

            using (WebApp.Start("http://*****:*****@"..\..\wwwroot")
                });
                app.UseStaticFiles(new StaticFileOptions
                {
                    RequestPath = new PathString("/cedarjs"),
                    FileSystem = new PhysicalFileSystem(@"..\..\..\Cedar.CommandHandling.Http.Js")
                });
                app.Map("/test/commands", commandsApp => commandsApp.Use(commandHandlingMiddleware));
            }))
            {
                Process.Start("http://localhost:8080/index.html");
                Console.WriteLine("Press any key to exit");
                Console.ReadKey();
            }
        }
コード例 #7
0
        static void Main()
        {
            Func <IFoo> getFoo              = () => new DummyFoo();
            var         module              = new CommandModule(getFoo);
            var         resolver            = new CommandHandlerResolver(module);
            var         commandMediaTypeMap = new CommandMediaTypeMap(new CommandMediaTypeWithQualifierVersionFormatter())
            {
                // Use a string to decouple command name from the command clr type. This will ensure
                // refactoring, i.e. moving CommandThatHasASyncHandler or renaming it, won't change your http API.
                { "CommandThatHasASyncHandler", typeof(CommandThatHasASyncHandler) },

                // Can use typeof().Name if you are not concerned with backwards compat or versioning.
                { typeof(CommandThatHasAnAsyncHandler).Name, typeof(CommandThatHasAnAsyncHandler) },
            };
            var settings = new CommandHandlingSettings(resolver, commandMediaTypeMap);
            var commandHandlingMiddleware = CommandHandlingMiddleware.HandleCommands(settings);

            // 5. Add the middleware to your owin pipeline
            using (WebApp.Start("http://localhost:8080",
                                app =>
            {
                app.Use(commandHandlingMiddleware);
            }))
            {
                Console.WriteLine("Press any key");
            }
        }
コード例 #8
0
 public ScenarioRunner(CommandHandlerResolver resolver, IStreamStore store, JsonSerializerSettings settings, EventMapping mapping, StreamNameConverter converter)
 {
     _resolver  = resolver ?? throw new ArgumentNullException(nameof(resolver));
     _store     = store ?? throw new ArgumentNullException(nameof(store));
     _settings  = settings ?? throw new ArgumentNullException(nameof(settings));
     _mapping   = mapping ?? throw new ArgumentNullException(nameof(mapping));
     _converter = converter ?? throw new ArgumentNullException(nameof(converter));
 }
コード例 #9
0
        public async Task Example_exception_handling()
        {
            var resolver = new CommandHandlerResolver(new CommandModule());
            var settings = new CommandHandlingSettings(resolver)
            {
                // 10. Specify the exception -> HttpProblemDetails mapper here
                MapProblemDetailsFromException = MapExceptionToProblemDetails
            };
            var middleware = CommandHandlingMiddleware.HandleCommands(settings);

            using (HttpClient client = middleware.CreateEmbeddedClient())
            {
                // 11. Handling standard exceptions.
                try
                {
                    await client.PutCommand(new CommandThatThrowsStandardException(), Guid.NewGuid());
                }
                catch (HttpRequestException ex)
                {
                    Console.WriteLine(ex.Message);
                }

                // 12. Handling explicit HttpProblemDetailsExceptions
                try
                {
                    await client.PutCommand(new CommandThatThrowsProblemDetailsException(), Guid.NewGuid());
                }
                catch (HttpProblemDetailsException <HttpProblemDetails> ex)
                {
                    Console.WriteLine(ex.ProblemDetails.Detail);
                    Console.WriteLine(ex.ProblemDetails.Status);
                }

                // 13. Handling mapped exceptions, same as #6
                try
                {
                    await client.PutCommand(new CommandThatThrowsMappedException(), Guid.NewGuid());
                }
                catch (HttpProblemDetailsException <HttpProblemDetails> ex)
                {
                    Console.WriteLine(ex.ProblemDetails.Detail);
                    Console.WriteLine(ex.ProblemDetails.Status);
                }

                // 14. Handling custom HttpProblemDetailExceptions
                try
                {
                    await client.PutCommand(new CommandThatThrowsCustomProblemDetailsException(), Guid.NewGuid());
                }
                catch (CustomHttpProblemDetailsException ex)
                {
                    Console.WriteLine(ex.ProblemDetails.Detail);
                    Console.WriteLine(ex.ProblemDetails.Status);
                    Console.WriteLine(ex.ProblemDetails.Name);
                }
            }
        }
コード例 #10
0
        public void Throws_nice_exception_if_no_handler_found()
        {
            var module   = new BadlyConfiguredCommandHandlerModule();
            var resolver = new CommandHandlerResolver(module);

            Func <Task <long> > dispatch = async() => await resolver.Dispatch(Guid.NewGuid(), new Command());

            dispatch.ShouldThrowAsync <ApplicationException>($"No handler was found for command {typeof(Command).FullName}");
        }
コード例 #11
0
        public void Can_resolve_handler()
        {
            var module = new TestCommandHandlerModule();
            var resolver = new CommandHandlerResolver(module);

            Handler<CommandMessage<Command>> handler = resolver.Resolve<Command>();

            handler.Should().NotBeNull();
        }
コード例 #12
0
        public async Task Can_dispatch()
        {
            var module = new TestCommandHandlerModule();
            var resolver = new CommandHandlerResolver(module); 

            await resolver.Dispatch(Guid.NewGuid(), new Command());

            module.Counter.Should().Be(1);
        }
コード例 #13
0
        public void Can_resolve_handler()
        {
            var module   = new TestCommandHandlerModule();
            var resolver = new CommandHandlerResolver(module);

            var handler = resolver.Resolve <Command>();

            handler.ShouldNotBeNull();
        }
コード例 #14
0
        public async Task Can_dispatch()
        {
            var module   = new TestCommandHandlerModule();
            var resolver = new CommandHandlerResolver(module);

            await resolver.Dispatch(Guid.NewGuid(), new Command());

            module.BaseCommandCounter.ShouldBe(1);
            module.CommandCounter.ShouldBe(1);
        }
コード例 #15
0
        private ICommandHandler <TCommand, TResult> GetComandHandler <TCommand, TResult>() where TCommand : ICommand
        {
            var handler = CommandHandlerResolver.Resolve <TCommand, TResult>(this);

            if (handler == null)
            {
                throw new CommandHandlerNotFoundException($"Не наден обработчик комманд для {typeof(TCommand).ToString()}.");
            }

            return(handler);
        }
コード例 #16
0
        public async Task MultiplePipesPassValueCorrectly()
        {
            var module   = new TestICommandHandlerModuleForMultiplePipesPassingValues(5);
            var resolver = new CommandHandlerResolver(module);

            await resolver.Dispatch(Guid.NewGuid(), new Command());

            module.ExecutionOrder.ShouldBe(new List <string> {
                "Pipe1.Before", "Pipe2.Before", "Handle", "Pipe2.After -1", "Pipe1.After 5"
            });
        }
コード例 #17
0
        public async Task PipesRunInCorrectOrder()
        {
            var module   = new TestICommandHandlerModuleForPipeOrder();
            var resolver = new CommandHandlerResolver(module);

            await resolver.Dispatch(Guid.NewGuid(), new Command());

            module.ExecutionOrder.ShouldBe(new List <string> {
                "Pipe.Before", "Handle", "Pipe.After"
            });
        }
コード例 #18
0
        public virtual void Publish <TCommand>(TCommand command)
            where TCommand : ICommand <TAuthenticationToken>
        {
            // We only set these two properties as they are not going to be available across the thread/task
            if (command.AuthenticationToken == null || command.AuthenticationToken.Equals(default(TAuthenticationToken)))
            {
                command.AuthenticationToken = AuthenticationTokenHelper.GetAuthenticationToken();
            }
            command.CorrelationId = CorrelationIdHelper.GetCorrelationId();

            bool result = CommandHandlerResolver.Ask <bool>(command).Result;
        }
コード例 #19
0
        public void Configuration(IAppBuilder app)
        {
            app.Map("/api/commands", builder =>
            {
                var moviesCommandModule    = TinyIoCContainer.Current.Resolve <MoviesCommandModule>();
                var directorsCommandModule = TinyIoCContainer.Current.Resolve <DirectorsCommandModule>();
                var resolver = new CommandHandlerResolver(moviesCommandModule, directorsCommandModule);
                var settings = new CommandHandlingSettings(resolver);

                var commandHandlingMiddleware = CommandHandlingMiddleware.HandleCommands(settings);
                builder.Use(commandHandlingMiddleware);
            });
        }
コード例 #20
0
        public void Command_should_call_service()
        {
            const string name = "jrustle";
            var foo = A.Fake<IFoo>();
            A.CallTo(() => foo.Bar(name));
            var sut = new CommandHandlerResolver(new CommandModule(() => foo));
            var command = new Command { Name = name };

            sut.Resolve<Command>()(
                new CommandMessage<Command>(Guid.NewGuid(), command),
                CancellationToken.None);

            A.CallTo(() => foo.Bar(name)).MustHaveHappened(Repeated.Exactly.Once);
        }
コード例 #21
0
            protected virtual void ExecuteReceive(ICommand <TAuthenticationToken> command)
            {
                try
                {
                    AuthenticationTokenHelper.SetAuthenticationToken(command.AuthenticationToken);
                    CorrelationIdHelper.SetCorrelationId(command.CorrelationId);
                    CommandHandlerResolver.Send(command);

                    Sender.Tell(true);
                }
                catch
                {
                    Sender.Tell(false);
                    throw;
                }
            }
コード例 #22
0
        static void Main()
        {
            Func <IFoo> getFoo   = () => new DummyFoo();
            var         resolver = new CommandHandlerResolver(new CommandModule(getFoo));
            var         settings = new CommandHandlingSettings(resolver);
            var         commandHandlingMiddleware = CommandHandlingMiddleware.HandleCommands(settings);

            // 5. Add the middleware to your owin pipeline
            using (WebApp.Start("http://localhost:8080",
                                app =>
            {
                app.Use(commandHandlingMiddleware);
            }))
            {
                Console.WriteLine("Press any key");
            }
        }
コード例 #23
0
        public void Command_should_call_service()
        {
            const string name = "jrustle";
            var          foo  = A.Fake <IFoo>();

            A.CallTo(() => foo.Bar(name));
            var sut     = new CommandHandlerResolver(new CommandModule(() => foo));
            var command = new Command {
                Name = name
            };

            sut.Resolve <Command>()(
                new CommandMessage <Command>(Guid.NewGuid(), command),
                CancellationToken.None);

            A.CallTo(() => foo.Bar(name)).MustHaveHappened(Repeated.Exactly.Once);
        }
コード例 #24
0
        public async Task Can_invoke_command_over_http()
        {
            // 1. Setup the middlware
            var resolver   = new CommandHandlerResolver(new CommandModule());
            var settings   = new CommandHandlingSettings(resolver);
            var middleware = CommandHandlingMiddleware.HandleCommands(settings);

            // 2. Create an embedded HttpClient. This allows invoking of the
            //    HttpPipeline in-memory without a server / listener.
            using (HttpClient client = middleware.CreateEmbeddedClient())
            {
                // 3. This is as close as you can get to simulating a real client call
                //    without needing real server.
                //    Can use this to do acceptance testing also.
                await client.PutCommand(new Command(), Guid.NewGuid());
            }
        }
コード例 #25
0
        public async Task Can_invoke_command_over_http()
        {
            // 1. Setup the middlware
            var resolver = new CommandHandlerResolver(new CommandModule());
            var commandMediaTypeMap = new CommandMediaTypeMap(new CommandMediaTypeWithQualifierVersionFormatter())
            {
                { typeof(Command).FullName.ToLower(), typeof(Command) }
            };
            var settings = new CommandHandlingSettings(resolver, commandMediaTypeMap);
            var middleware = CommandHandlingMiddleware.HandleCommands(settings);

            // 2. Create an embedded HttpClient. This allows invoking of the 
            //    HttpPipeline in-memory without a server / listener.
            using(HttpClient client = middleware.CreateEmbeddedClient())
            {
                // 3. This is as close as you can get to simulating a real client call
                //    without needing real server. 
                //    Can use this to do acceptance testing also.
                await client.PutCommand(new Command(), Guid.NewGuid(), commandMediaTypeMap);
            }
        }
コード例 #26
0
        public async Task Can_invoke_command_over_http()
        {
            var resolver            = new CommandHandlerResolver(new CommandModule());
            var commandMediaTypeMap = new CommandMediaTypeMap(new CommandMediaTypeWithQualifierVersionFormatter())
            {
                { typeof(Command).FullName.ToLower(), typeof(Command) }
            };

            // 1. Create the serializer
            var jsonSerializer = new JsonSerializer();
            var settings       = new CommandHandlingSettings(resolver, commandMediaTypeMap)
            {
                // 2. Customize the deserialization
                DeserializeCommand = (commandReader, type) =>
                {
                    using (var reader = new JsonTextReader(commandReader))
                    {
                        return(jsonSerializer.Deserialize(reader, type));
                    }
                }
            };
            var middleware = CommandHandlingMiddleware.HandleCommands(settings);

            // 3. Customize the serialization
            SerializeCommand serializeCommand = (writer, command) =>
            {
                jsonSerializer.Serialize(writer, command);
            };

            // 3. Create an embedded HttpClient. This allows invoking of the
            //    HttpPipeline in-memory without a server / listener.
            using (HttpClient client = middleware.CreateEmbeddedClient())
            {
                // 3. This is as close as you can get to simulating a real client call
                //    without needing real server.
                //    Can use this to do acceptance testing also.
                await client.PutCommand(new Command(), Guid.NewGuid(), commandMediaTypeMap, serializeCommand : serializeCommand);
            }
        }
コード例 #27
0
        public async Task Can_invoke_command_over_http()
        {
            var resolver = new CommandHandlerResolver(new CommandModule());
            var commandMediaTypeMap = new CommandMediaTypeMap(new CommandMediaTypeWithQualifierVersionFormatter())
            {
                { typeof(Command).FullName.ToLower(), typeof(Command) }
            };

            // 1. Create the serializer
            var jsonSerializer = new JsonSerializer();
            var settings = new CommandHandlingSettings(resolver, commandMediaTypeMap)
            {
                // 2. Customize the deserialization
                DeserializeCommand = (commandReader, type) =>
                {
                    using(var reader = new JsonTextReader(commandReader))
                    {
                        return jsonSerializer.Deserialize(reader, type);
                    }
                }
            };
            var middleware = CommandHandlingMiddleware.HandleCommands(settings);

            // 3. Customize the serialization
            SerializeCommand serializeCommand = (writer, command) =>
            {
                jsonSerializer.Serialize(writer, command);
            };
            // 3. Create an embedded HttpClient. This allows invoking of the 
            //    HttpPipeline in-memory without a server / listener.
            using(HttpClient client = middleware.CreateEmbeddedClient())
            {
                // 3. This is as close as you can get to simulating a real client call
                //    without needing real server. 
                //    Can use this to do acceptance testing also.
                await client.PutCommand(new Command(), Guid.NewGuid(), commandMediaTypeMap, serializeCommand: serializeCommand);
            }
        }
コード例 #28
0
        static void Main()
        {
            var resolver = new CommandHandlerResolver(new CommandModule());

            // 1. Create a map to resolve types from a key.
            // This could of course be done with reflection + conventions.
            // For the sake of example, we're going to be explict.
            var commandMap = new[]
            {
                typeof(CommandVersioning.V1.Command),
                typeof(CommandVersioning.V2.Command),
            }.ToDictionary(t => t.Name.ToLowerInvariant(), t => t);

            var resolveCommandType = new ResolveCommandType((typeName, version) =>
            {
                // 2. In this example, we're not handling unversioned commands. You
                // may of course handle them.
                if (version == null)
                {
                    return(null); // 3. Return null if the command type can't be resolved.
                }

                // 4. Here we're just converting the typeName to a key that matches our
                // convetion.
                var typeNameSegments = typeName.Split('.').ToList();                // my.type.name -> { my, type, name }
                typeNameSegments.Insert(typeNameSegments.Count - 1, "v" + version); // { my, type, name } -> { my, type, vX, name }
                typeName = string.Join(".", typeNameSegments);                      // { my, type, vX, name } -> my.type.vX.name

                Type commandType;
                commandMap.TryGetValue(typeName, out commandType);
                return(commandType);
            });

            // 5. CommandHandlingSettings has a contructor overload to pass in the command type resolver.
            var settings = new CommandHandlingSettings(resolver, resolveCommandType);
        }
コード例 #29
0
        public void Setup()
        {
            commandHandlers = new List<ICommandHandler>();

            sut = new CommandHandlerResolver(commandHandlers);
        }
コード例 #30
0
 public CommandDispatcher(IEnumerable <CommandHandlerModule> commandHandlerModules)
 {
     _resolver = CommandResolve.WhenEqualToHandlerMessageType(commandHandlerModules);
 }
コード例 #31
0
        public ProcessManagerHandlerTests()
        {
            TestLogger.Configure();

            var source = new TaskCompletionSource <bool>();

            _nodeStarted = source.Task;

            var notListening = new IPEndPoint(IPAddress.None, 0);

            _node = EmbeddedVNodeBuilder.AsSingleNode()
                    .WithInternalTcpOn(notListening)
                    .WithExternalTcpOn(notListening)
                    .WithInternalHttpOn(notListening)
                    .WithExternalHttpOn(notListening);

            _node.NodeStatusChanged += (_, e) =>
            {
                if (e.NewVNodeState != VNodeState.Master)
                {
                    return;
                }

                source.SetResult(true);
            };

            _node.Start();

            _connection = EmbeddedEventStoreConnection.Create(_node);

            _commands = new List <object>();

            _serializer = new DefaultGetEventStoreJsonSerializer();

            var commandHandlerModule = new CommandHandlerModule();

            commandHandlerModule.For <ShipOrder>()
            .Handle((message, _) =>
            {
                _commands.Add(message.Command);
                return(Task.FromResult(0));
            });
            commandHandlerModule.For <BillCustomer>()
            .Handle((message, _) =>
            {
                _commands.Add(message.Command);
                return(Task.FromResult(0));
            });

            var resolver = new CommandHandlerResolver(commandHandlerModule);
            var commandHandlingMiddleware =
                CommandHandlingMiddleware.HandleCommands(new CommandHandlingSettings(resolver));
            var embeddedClient = commandHandlingMiddleware.CreateEmbeddedClient();

            var processHandler = ProcessHandler.For <OrderFulfillment, CompareablePosition>(
                (command, token) => embeddedClient.PutCommand(command, Guid.NewGuid()),
                new EventStoreClientProcessManagerCheckpointRepository(_connection, _serializer))
                                 .CorrelateBy <OrderPlaced>(e => e.DomainEvent.OrderId.ToString())
                                 .CorrelateBy <OrderShipped>(e => e.DomainEvent.OrderId.ToString())
                                 .CorrelateBy <BillingSucceeded>(e => e.DomainEvent.OrderId.ToString())
                                 .CorrelateBy <BillingFailed>(e => e.DomainEvent.OrderId.ToString());


            _dispatcher = new ResolvedEventDispatcher(_connection,
                                                      new DefaultGetEventStoreJsonSerializer(),
                                                      new InMemoryCheckpointRepository(),
                                                      processHandler.BuildHandlerResolver(),
                                                      () => { });

            _orderId       = Guid.NewGuid();
            _streamId      = ("orders-" + _orderId.ToString("n")).FormatStreamIdWithBucket();
            _correlationId = _orderId.ToString();
        }
コード例 #32
0
        public ProcessManagerHandlerTests()
        {
            TestLogger.Configure();

            var source = new TaskCompletionSource<bool>();
            _nodeStarted = source.Task;

            var notListening = new IPEndPoint(IPAddress.None, 0);

            _node = EmbeddedVNodeBuilder.AsSingleNode()
                .WithInternalTcpOn(notListening)
                .WithExternalTcpOn(notListening)
                .WithInternalHttpOn(notListening)
                .WithExternalHttpOn(notListening);

            _node.NodeStatusChanged += (_, e) =>
            {
                if(e.NewVNodeState != VNodeState.Master)
                {
                    return;
                }

                source.SetResult(true);
            };

            _node.Start();

            _connection = EmbeddedEventStoreConnection.Create(_node);

            _commands = new List<object>();

            _serializer = new DefaultGetEventStoreJsonSerializer();

            var commandHandlerModule = new CommandHandlerModule();
            commandHandlerModule.For<ShipOrder>()
                .Handle((message, _) =>
                {
                    _commands.Add(message.Command);
                    return Task.FromResult(0);
                });
            commandHandlerModule.For<BillCustomer>()
                .Handle((message, _) =>
                {
                    _commands.Add(message.Command);
                    return Task.FromResult(0);
                });

            var resolver = new CommandHandlerResolver(commandHandlerModule);
            var commandHandlingMiddleware =
                CommandHandlingMiddleware.HandleCommands(new CommandHandlingSettings(resolver));
            var embeddedClient = commandHandlingMiddleware.CreateEmbeddedClient();

            var processHandler = ProcessHandler.For<OrderFulfillment, CompareablePosition>(
                (command, token) => embeddedClient.PutCommand(command, Guid.NewGuid()),
                new EventStoreClientProcessManagerCheckpointRepository(_connection, _serializer))
                .CorrelateBy<OrderPlaced>(e => e.DomainEvent.OrderId.ToString())
                .CorrelateBy<OrderShipped>(e => e.DomainEvent.OrderId.ToString())
                .CorrelateBy<BillingSucceeded>(e => e.DomainEvent.OrderId.ToString())
                .CorrelateBy<BillingFailed>(e => e.DomainEvent.OrderId.ToString());


            _dispatcher = new ResolvedEventDispatcher(_connection,
                new DefaultGetEventStoreJsonSerializer(),
                new InMemoryCheckpointRepository(),
                processHandler.BuildHandlerResolver(),
                () => { });

            _orderId = Guid.NewGuid();
            _streamId = ("orders-" + _orderId.ToString("n")).FormatStreamIdWithBucket();
            _correlationId = _orderId.ToString();
        }