public override async Task InvokeAsync <TCommand>( TCommand command, CommandRequestRegistration <TCommand> registration, HttpContext context) { this.logger.LogInformation($"{{LogKey:l}} command request dispatch (name={registration.CommandType.PrettyName()}, id={command.Id}, type=queue)", LogKeys.AppCommand); //var wrapper = new CommandWrapper().SetCommand<TCommand>(command); var wrapper = new CommandRequestWrapper().SetCommand(command); await this.queue.EnqueueAsync(wrapper).AnyContext(); var metrics = await this.queue.GetMetricsAsync().AnyContext(); this.logger.LogInformation($"{{LogKey:l}} request command queue (enqueued=#{metrics.Enqueued}, queued=#{metrics.Queued})", LogKeys.AppCommand); this.logger.LogInformation($"queued COMMAND: {command.Dump()}"); await context.Response.Location($"naos/commands/{command.Id}/response").AnyContext(); await context.Response.Header(CommandRequestHeaders.CommandId, command.Id).AnyContext(); await this.StoreCommand(wrapper).AnyContext(); // the extension chain is terminated here }
public override async Task InvokeAsync <TCommand>( TCommand command, CommandRequestRegistration <TCommand> registration, HttpContext context) { this.logger.LogInformation($"{{LogKey:l}} request command dispatch (name={registration.CommandType.PrettyName()}, id={command.Id}), type=mediator)", LogKeys.AppCommand); var response = await this.mediator.Send(command).AnyContext(); // https://github.com/jbogard/MediatR/issues/385 if (response != null) { var jResponse = JObject.FromObject(response); if (!jResponse.GetValueByPath <bool>("cancelled")) { registration?.OnSuccess?.Invoke(command, context); } else { var cancelledReason = jResponse.GetValueByPath <string>("cancelledReason"); await context.Response.BadRequest(cancelledReason.SliceTill(":")).AnyContext(); } } await context.Response.Header(CommandRequestHeaders.CommandId, command.Id).AnyContext(); // the extension chain is terminated here }
public override async Task InvokeAsync <TCommand>( TCommand command, CommandRequestRegistration <TCommand> registration, HttpContext context) { this.logger.LogInformation($"{{LogKey:l}} command request received (name={registration.CommandType.PrettyName()}, id={command.Id})", LogKeys.AppCommand); // continue with next extension await base.InvokeAsync(command, registration, context).AnyContext(); }
private static void AddBodyOperation(OpenApiOperation operation, CommandRequestRegistration registration, DocumentProcessorContext context) { operation.Parameters.Add(new OpenApiParameter { //Description = "request model", Kind = OpenApiParameterKind.Body, Name = (registration.CommandType ?? typeof(object)).PrettyName(), //"model", Type = JsonObjectType.Object, Schema = CreateSchema(registration, context), //Example = registration.CommandType != null ? Factory.Create(registration.CommandType) : null //new Commands.Domain.EchoCommand() { Message = "test"}, }); }
public virtual async Task InvokeAsync <TCommand>( TCommand command, CommandRequestRegistration <TCommand> registration, HttpContext context) where TCommand : Command <object> { if (this.next != null) { await this.next.InvokeAsync <TCommand>(command, registration, context).AnyContext(); } // chain is terminated here }
private static void AddResponseHeaders(OpenApiOperation operation, CommandRequestRegistration registration) { foreach (var response in operation.Responses) { response.Value.Headers.Add(CommandRequestHeaders.CommandId, new JsonSchema { Type = JsonObjectType.String }); if (registration.IsQueued) { response.Value.Headers.Add("Location", new JsonSchema { Type = JsonObjectType.String }); } } }
public override async Task InvokeAsync <TCommand, TResponse>( TCommand command, CommandRequestRegistration <TCommand, TResponse> registration, HttpContext context) { using (var scope = this.tracer?.BuildSpan( $"command request {command.GetType().PrettyName()}".ToLowerInvariant(), LogKeys.AppCommand, SpanKind.Consumer).Activate(this.logger)) { // start a whole new SERVER span later, which is the parent for the current 'COMMAND REQUEST' span command.Properties.Add(CommandPropertyKeys.TraceId, scope?.Span?.TraceId); // propagate the span infos command.Properties.Add(CommandPropertyKeys.TraceSpanId, scope?.Span?.SpanId); // propagate the span infos command.Properties.Add(CommandPropertyKeys.TraceSampled, scope?.Span?.IsSampled); // propagate the span infos // continue with next extension await base.InvokeAsync(command, registration, context).AnyContext(); } }
private static JsonSchema CreateSchema(CommandRequestRegistration registration, DocumentProcessorContext context) { return(context.SchemaGenerator.Generate(registration.CommandType, context.SchemaResolver)); //var schema = result.AllOf.FirstOrDefault(); //if (schema != null) //{ // // workaround: remove invalid first $ref in allof https://github.com/RicoSuter/NSwag/issues/2119 // result.AllOf.Remove(schema); //} // remove some more $refs //foreach(var definition in result.Definitions.Safe()) //{ // var s = definition.Value.AllOf.FirstOrDefault(); // if(s != null) // { // definition.Value.AllOf.Remove(s); // } //} }
private static void AddQueryOperation(OpenApiOperation operation, CommandRequestRegistration registration) { foreach (var property in registration.CommandType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) { // translate commandType properties to many OpenApiParameters if (!property.CanWrite || !property.CanRead) { continue; } var type = JsonObjectType.String; if (property.PropertyType == typeof(int) || property.PropertyType == typeof(short)) { type = JsonObjectType.Integer; } else if (property.PropertyType == typeof(decimal) || property.PropertyType == typeof(float) || property.PropertyType == typeof(long)) { type = JsonObjectType.Number; } else if (property.PropertyType == typeof(bool)) { type = JsonObjectType.Boolean; } else if (property.PropertyType == typeof(object)) { type = JsonObjectType.Object; // TODO: does not work for child objects } operation.Parameters.Add(new OpenApiParameter { //Description = "request model", Kind = registration.Route.Contains($"{{{property.Name}", System.StringComparison.OrdinalIgnoreCase) ? OpenApiParameterKind.Path : OpenApiParameterKind.Query, Name = property.Name.Camelize(), Type = type, }); } }
private async Task HandleCommandWithoutResponse <TCommand>( object command, CommandRequestRegistration <TCommand> registration, HttpContext context) where TCommand : Command <object> { // registration will be resolved to the actual type with proper generic types. var i = typeof(RequestCommandRegistration<TCommand, TResponse>); if (command != null) { var extensions = this.EnsureExtensions(context); this.logger.LogDebug($"{{LogKey:l}} command request extensions chain: {extensions.Select(e => e.GetType().PrettyName()).ToString("|")} (name={registration.CommandType.Name})", LogKeys.AppCommand); if (extensions.Count > 0) // invoke all chained extensions { var tCommand = command as TCommand; tCommand?.Update(correlationId: context.GetCorrelationId()); // use correlationid from inbound http request await extensions[0].InvokeAsync(tCommand, registration, context).AnyContext(); } else { throw new Exception("Command request not executed, no dispatcher middleware extensions configured"); } } }
public override async Task InvokeAsync <TCommand>( TCommand command, CommandRequestRegistration <TCommand> registration, HttpContext context) { if (this.tracer == null) { // continue with next extension await base.InvokeAsync(command, registration, context).AnyContext(); } else { using (var scope = this.tracer.BuildSpan( $"command request {command.GetType().PrettyName()}".ToLowerInvariant(), LogKeys.AppCommand, SpanKind.Consumer).Activate(this.logger)) { // start a whole new SERVER span later, which is the parent for the current 'COMMAND REQUEST' span command.Properties.Add(CommandPropertyKeys.TraceId, scope.Span.TraceId); // propagate the span infos command.Properties.Add(CommandPropertyKeys.TraceSpanId, scope.Span.SpanId); // propagate the span infos command.Properties.Add(CommandPropertyKeys.TraceSampled, scope.Span.IsSampled); // propagate the span infos if (scope.Span.IsSampled == false) { this.logger.LogDebug($"{{LogKey:l}} span not sampled (id={scope.Span.SpanId})", LogKeys.Tracing); } else { this.logger.LogDebug($"{{LogKey:l}} span sampled (id={scope.Span.SpanId})", LogKeys.Tracing); } // continue with next extension await base.InvokeAsync(command, registration, context).AnyContext(); } } }
private static void AddOperationParameters(OpenApiOperation operation, string method, CommandRequestRegistration registration, DocumentProcessorContext context) { if (registration.CommandType != null) { if (method.SafeEquals("get") || method.SafeEquals("delete")) { AddQueryOperation(operation, registration); } else if (method.SafeEquals("post") || method.SafeEquals("put") || method.SafeEquals(string.Empty)) { AddBodyOperation(operation, registration, context); } else { // TODO: ignore for now, or throw? +log } } }