//private static void AddErrorReasonToContent(CapReceivedMessage message, Exception exception) //{ // message.Content = Helper.AddExceptionProperty(message.Content, exception); //} private async Task InvokeConsumerMethodAsync(MediumMessage message, ConsumerExecutorDescriptor descriptor, CancellationToken cancellationToken) { var consumerContext = new ConsumerContext(descriptor, message.Origin); var tracingTimestamp = TracingBefore(message.Origin, descriptor.MethodInfo); try { var ret = await Invoker.InvokeAsync(consumerContext, cancellationToken); TracingAfter(tracingTimestamp, message.Origin, descriptor.MethodInfo); if (!string.IsNullOrEmpty(ret.CallbackName)) { var header = new Dictionary <string, string>() { [Headers.CorrelationId] = message.Origin.GetId(), [Headers.CorrelationSequence] = (message.Origin.GetCorrelationSequence() + 1).ToString() }; await _provider.GetService <ICapPublisher>().PublishAsync(ret.CallbackName, ret.Result, header, cancellationToken); } } catch (OperationCanceledException) { //ignore } catch (Exception ex) { var e = new SubscriberExecutionFailedException(ex.Message, ex); TracingError(tracingTimestamp, message.Origin, descriptor.MethodInfo, e); throw e; } }
public async Task <ConsumerExecutedResult> InvokeAsync(ConsumerContext context) { _logger.LogDebug("Executing consumer Topic: {0}", context.ConsumerDescriptor.MethodInfo.Name); var executor = ObjectMethodExecutor.Create( context.ConsumerDescriptor.MethodInfo, context.ConsumerDescriptor.ImplTypeInfo); using (var scope = _serviceProvider.CreateScope()) { var provider = scope.ServiceProvider; var serviceType = context.ConsumerDescriptor.ImplTypeInfo.AsType(); var obj = ActivatorUtilities.GetServiceOrCreateInstance(provider, serviceType); var jsonContent = context.DeliverMessage.Content; var message = _messagePacker.UnPack(jsonContent); object resultObj; if (executor.MethodParameters.Length > 0) { resultObj = await ExecuteWithParameterAsync(executor, obj, message.Content); } else { resultObj = await ExecuteAsync(executor, obj); } return(new ConsumerExecutedResult(resultObj, message.Id, message.CallbackName)); } }
public async Task <OperateResult> ExecuteAsync(CapReceivedMessage receivedMessage) { try { var executeDescriptorGroup = _selector.GetTopicExector(receivedMessage.Name); if (!executeDescriptorGroup.ContainsKey(receivedMessage.Group)) { var error = $"Topic:{receivedMessage.Name}, can not be found subscriber method."; throw new SubscriberNotFoundException(error); } // If there are multiple consumers in the same group, we will take the first var executeDescriptor = executeDescriptorGroup[receivedMessage.Group][0]; var consumerContext = new ConsumerContext(executeDescriptor, receivedMessage.ToMessageContext()); var ret = await Invoker.InvokeAsync(consumerContext); if (!string.IsNullOrEmpty(ret.CallbackName)) { await _callbackMessageSender.SendAsync(ret.MessageId, ret.CallbackName, ret.Result); } return(OperateResult.Success); } catch (Exception ex) { _logger.ConsumerMethodExecutingFailed($"Group:{receivedMessage.Group}, Topic:{receivedMessage.Name}", ex); return(OperateResult.Failed(ex)); } }
public async Task <OperateResult> ExecuteAsync(CapReceivedMessage receivedMessage) { if (!_selector.TryGetTopicExector(receivedMessage.Name, receivedMessage.Group, out var executor)) { var error = "message can not be found subscriber. Message:" + receivedMessage; error += "\r\n see: https://github.com/dotnetcore/CAP/issues/63"; throw new SubscriberNotFoundException(error); } var consumerContext = new ConsumerContext(executor, receivedMessage.ToMessageContext()); try { var ret = await Invoker.InvokeAsync(consumerContext); if (!string.IsNullOrEmpty(ret.CallbackName)) { await _callbackMessageSender.SendAsync(ret.MessageId, ret.CallbackName, ret.Result); } return(OperateResult.Success); } catch (Exception ex) { _logger.ConsumerMethodExecutingFailed($"Group:{receivedMessage.Group}, Topic:{receivedMessage.Name}", ex); return(OperateResult.Failed(ex)); } }
public IConsumerInvoker CreateInvoker(ConsumerContext consumerContext) { var context = new ConsumerInvokerContext(consumerContext) { Result = new DefaultConsumerInvoker(_logger, _serviceProvider, _modelBinderFactory, consumerContext) }; return(context.Result); }
public async Task <ConsumerExecutedResult> InvokeAsync(ConsumerContext context, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); var methodInfo = context.ConsumerDescriptor.MethodInfo; _logger.LogDebug("Executing subscriber method : {0}", methodInfo.Name); var executor = _executors.GetOrAdd(methodInfo.MetadataToken, x => ObjectMethodExecutor.Create(methodInfo, context.ConsumerDescriptor.ImplTypeInfo)); using var scope = _serviceProvider.CreateScope(); var provider = scope.ServiceProvider; var obj = GetInstance(provider, context); var message = context.DeliverMessage; var parameterDescriptors = context.ConsumerDescriptor.Parameters; var executeParameters = new object[parameterDescriptors.Count]; for (var i = 0; i < parameterDescriptors.Count; i++) { if (parameterDescriptors[i].IsFromCap) { executeParameters[i] = new CapHeader(message.Headers); } else { if (message.Value != null) { if (message.Value is JToken jToken) //reading from storage { executeParameters[i] = jToken.ToObject(parameterDescriptors[i].ParameterType); } else { var converter = TypeDescriptor.GetConverter(parameterDescriptors[i].ParameterType); if (converter.CanConvertFrom(message.Value.GetType())) { executeParameters[i] = converter.ConvertFrom(message.Value); } else { executeParameters[i] = Convert.ChangeType(message.Value, parameterDescriptors[i].ParameterType); } } } } } var resultObj = await ExecuteWithParameterAsync(executor, obj, executeParameters); return(new ConsumerExecutedResult(resultObj, message.GetId(), message.GetCallbackName())); }
public async Task <ConsumerExecutedResult> InvokeAsync(ConsumerContext context, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); var methodInfo = context.ConsumerDescriptor.MethodInfo; _logger.LogDebug("Executing subscriber method : {0}", methodInfo.Name); var executor = _executors.GetOrAdd(methodInfo.MetadataToken, x => ObjectMethodExecutor.Create(methodInfo, context.ConsumerDescriptor.ImplTypeInfo)); using (var scope = _serviceProvider.CreateScope()) { var provider = scope.ServiceProvider; var srvType = context.ConsumerDescriptor.ServiceTypeInfo?.AsType(); var implType = context.ConsumerDescriptor.ImplTypeInfo.AsType(); object obj = null; if (srvType != null) { obj = provider.GetServices(srvType).FirstOrDefault(o => o.GetType() == implType); } if (obj == null) { obj = ActivatorUtilities.GetServiceOrCreateInstance(provider, implType); } var message = context.DeliverMessage; var parameterDescriptors = context.ConsumerDescriptor.Parameters; var executeParameters = new object[parameterDescriptors.Count]; for (var i = 0; i < parameterDescriptors.Count; i++) { if (parameterDescriptors[i].IsFromCap) { executeParameters[i] = new CapHeader(message.Headers); } else { if (message.Value is JToken jToken) //reading from storage { executeParameters[i] = jToken.ToObject(parameterDescriptors[i].ParameterType); } else { executeParameters[i] = message.Value; } } } var resultObj = await ExecuteWithParameterAsync(executor, obj, executeParameters); return(new ConsumerExecutedResult(resultObj, message.GetId(), message.GetCallbackName())); } }
public IConsumerInvoker CreateInvoker(ConsumerContext consumerContext) { using (var scope = _serviceProvider.CreateScope()) { var context = new ConsumerInvokerContext(consumerContext) { Result = new DefaultConsumerInvoker(_logger, scope.ServiceProvider, _modelBinderFactory, consumerContext) }; return(context.Result); } }
public DefaultConsumerInvoker(ILogger logger, IServiceProvider serviceProvider, IModelBinderFactory modelBinderFactory, ConsumerContext consumerContext) { _modelBinderFactory = modelBinderFactory; _serviceProvider = serviceProvider; _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _consumerContext = consumerContext ?? throw new ArgumentNullException(nameof(consumerContext)); _executor = ObjectMethodExecutor.Create(_consumerContext.ConsumerDescriptor.MethodInfo, _consumerContext.ConsumerDescriptor.ImplTypeInfo); }
public DefaultConsumerInvoker(ILogger logger, IServiceProvider serviceProvider, IModelBinderFactory modelBinderFactory, ConsumerContext consumerContext) { _modelBinderFactory = modelBinderFactory; _serviceProvider = serviceProvider; _logger = logger; _consumerContext = consumerContext; _executor = ObjectMethodExecutor.Create(_consumerContext.ConsumerDescriptor.MethodInfo, _consumerContext.ConsumerDescriptor.ImplTypeInfo); }
protected virtual object GetInstance(IServiceProvider provider, ConsumerContext context) { var srvType = context.ConsumerDescriptor.ServiceTypeInfo?.AsType(); var implType = context.ConsumerDescriptor.ImplTypeInfo.AsType(); object obj = null; if (srvType != null) { obj = provider.GetServices(srvType).FirstOrDefault(o => o.GetType() == implType); } if (obj == null) { obj = ActivatorUtilities.GetServiceOrCreateInstance(provider, implType); } return obj; }
public async Task <ConsumerExecutedResult> InvokeAsync(ConsumerContext context, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); _logger.LogDebug("Executing consumer Topic: {0}", context.ConsumerDescriptor.MethodInfo.Name); var executor = ObjectMethodExecutor.Create( context.ConsumerDescriptor.MethodInfo, context.ConsumerDescriptor.ImplTypeInfo); using (var scope = _serviceProvider.CreateScope()) { var provider = scope.ServiceProvider; var srvType = context.ConsumerDescriptor.ServiceTypeInfo?.AsType(); var implType = context.ConsumerDescriptor.ImplTypeInfo.AsType(); object obj = null; if (srvType != null) { obj = provider.GetServices(srvType).FirstOrDefault(o => o.GetType() == implType); } if (obj == null) { obj = ActivatorUtilities.GetServiceOrCreateInstance(provider, implType); } var jsonContent = context.DeliverMessage.Content; var message = _messagePacker.UnPack(jsonContent); object resultObj; if (executor.MethodParameters.Length > 0) { resultObj = await ExecuteWithParameterAsync(executor, obj, message.Content); } else { resultObj = await ExecuteAsync(executor, obj); } return(new ConsumerExecutedResult(resultObj, message.Id, message.CallbackName)); } }
public object GetInstance(ConsumerContext context) { var srvType = context.ConsumerDescriptor.ServiceTypeInfo?.AsType(); var implType = context.ConsumerDescriptor.ImplTypeInfo.AsType(); object obj = null; if (srvType != null) { obj = _scope.ServiceProvider.GetServices(srvType).FirstOrDefault(o => o.GetType() == implType); } if (obj == null) { obj = ActivatorUtilities.GetServiceOrCreateInstance(_scope.ServiceProvider, implType); } return(obj); }
protected virtual object GetInstance(IServiceProvider provider, ConsumerContext context) { var srvType = context.ConsumerDescriptor.ServiceTypeInfo?.AsType(); var implType = context.ConsumerDescriptor.ImplTypeInfo.AsType(); object obj = null; if (srvType != null) { //obj = provider.GetServices(srvType).FirstOrDefault(o => o.GetType() == implType); var instance = provider.GetService <IServiceResolver>().ResolveRequired(srvType); var field = instance.GetType().GetTypeInfo().GetField("_implementation", BindingFlags.Instance | BindingFlags.NonPublic); var targetInstance = field.GetValue(instance); obj = targetInstance; } if (obj == null) { obj = ActivatorUtilities.GetServiceOrCreateInstance(provider, implType); } return(obj); }
public async Task<ConsumerExecutedResult> InvokeAsync(ConsumerContext context, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); var methodInfo = context.ConsumerDescriptor.MethodInfo; var reflectedTypeHandle = methodInfo.ReflectedType.TypeHandle.Value; var methodHandle = methodInfo.MethodHandle.Value; var key = $"{reflectedTypeHandle}_{methodHandle}"; var executor = _executors.GetOrAdd(key, x => ObjectMethodExecutor.Create(methodInfo, context.ConsumerDescriptor.ImplTypeInfo)); using var scope = _serviceProvider.CreateScope(); var provider = scope.ServiceProvider; var obj = GetInstance(provider, context); var message = context.DeliverMessage; var parameterDescriptors = context.ConsumerDescriptor.Parameters; var executeParameters = new object[parameterDescriptors.Count]; for (var i = 0; i < parameterDescriptors.Count; i++) { var parameterDescriptor = parameterDescriptors[i]; if (parameterDescriptor.IsFromCap) { executeParameters[i] = GetCapProvidedParameter(parameterDescriptor, message, cancellationToken); } else { if (message.Value != null) { if (_serializer.IsJsonType(message.Value)) // use ISerializer when reading from storage, skip other objects if not Json { executeParameters[i] = _serializer.Deserialize(message.Value, parameterDescriptor.ParameterType); } else { var converter = TypeDescriptor.GetConverter(parameterDescriptor.ParameterType); if (converter.CanConvertFrom(message.Value.GetType())) { executeParameters[i] = converter.ConvertFrom(message.Value); } else { if (parameterDescriptor.ParameterType.IsInstanceOfType(message.Value)) { executeParameters[i] = message.Value; } else { executeParameters[i] = Convert.ChangeType(message.Value, parameterDescriptor.ParameterType); } } } } } } var filter = provider.GetService<ISubscribeFilter>(); object resultObj = null; try { if (filter != null) { var etContext = new ExecutingContext(context, executeParameters); filter.OnSubscribeExecuting(etContext); executeParameters = etContext.Arguments; } resultObj = await ExecuteWithParameterAsync(executor, obj, executeParameters); if (filter != null) { var edContext = new ExecutedContext(context, resultObj); filter.OnSubscribeExecuted(edContext); resultObj = edContext.Result; } } catch (Exception e) { if (filter != null) { var exContext = new ExceptionContext(context, e); filter.OnSubscribeException(exContext); if (!exContext.ExceptionHandled) { throw exContext.Exception; } if (exContext.Result != null) { resultObj = exContext.Result; } } else { throw; } } return new ConsumerExecutedResult(resultObj, message.GetId(), message.GetCallbackName()); }
public ConsumerContext(ConsumerContext context) : this(context.ConsumerDescriptor, context.DeliverMessage) { }
public async Task <ConsumerExecutedResult> InvokeAsync(ConsumerContext context, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); var methodInfo = context.ConsumerDescriptor.MethodInfo; var reflectedType = methodInfo.ReflectedType.Name; _logger.LogDebug("Executing subscriber method : {0}", methodInfo.Name); var key = $"{methodInfo.Module.Name}_{reflectedType}_{methodInfo.MetadataToken}"; var executor = _executors.GetOrAdd(key, x => ObjectMethodExecutor.Create(methodInfo, context.ConsumerDescriptor.ImplTypeInfo)); using (var scope = _serviceProvider.GetService <ICapServiceScope>()) { var obj = scope.GetInstance(context); var message = context.DeliverMessage; var parameterDescriptors = context.ConsumerDescriptor.Parameters; var executeParameters = new object[parameterDescriptors.Count]; for (var i = 0; i < parameterDescriptors.Count; i++) { if (parameterDescriptors[i].IsFromCap) { executeParameters[i] = new CapHeader(message.Headers); } else { if (message.Value != null) { if (_serializer.IsJsonType(message.Value)) // use ISerializer when reading from storage, skip other objects if not Json { executeParameters[i] = _serializer.Deserialize(message.Value, parameterDescriptors[i].ParameterType); } else { var converter = TypeDescriptor.GetConverter(parameterDescriptors[i].ParameterType); if (converter.CanConvertFrom(message.Value.GetType())) { executeParameters[i] = converter.ConvertFrom(message.Value); } else { if (parameterDescriptors[i].ParameterType.IsInstanceOfType(message.Value)) { executeParameters[i] = message.Value; } else { executeParameters[i] = Convert.ChangeType(message.Value, parameterDescriptors[i].ParameterType); } } } } } } var resultObj = await ExecuteWithParameterAsync(executor, obj, executeParameters); return(new ConsumerExecutedResult(resultObj, message.GetId(), message.GetCallbackName())); } }