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)); }
public static CommandHandlerDispatcher Using(CommandHandlerResolver resolver) { if (resolver == null) { throw new ArgumentNullException(nameof(resolver)); } return((message, cancellationToken) => resolver(message)(message, cancellationToken)); }
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(); } }
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"); } }
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(); } }
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(); } }
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"); } }
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)); }
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); } } }
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}"); }
public void Can_resolve_handler() { var module = new TestCommandHandlerModule(); var resolver = new CommandHandlerResolver(module); Handler<CommandMessage<Command>> handler = resolver.Resolve<Command>(); handler.Should().NotBeNull(); }
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); }
public void Can_resolve_handler() { var module = new TestCommandHandlerModule(); var resolver = new CommandHandlerResolver(module); var handler = resolver.Resolve <Command>(); handler.ShouldNotBeNull(); }
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); }
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); }
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" }); }
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" }); }
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; }
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); }); }
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); }
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; } }
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"); } }
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); }
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()); } }
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); } }
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); } }
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); } }
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); }
public void Setup() { commandHandlers = new List<ICommandHandler>(); sut = new CommandHandlerResolver(commandHandlers); }
public CommandDispatcher(IEnumerable <CommandHandlerModule> commandHandlerModules) { _resolver = CommandResolve.WhenEqualToHandlerMessageType(commandHandlerModules); }
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(); }
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(); }