//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;
            }
        }
Beispiel #2
0
        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));
            }
        }
Beispiel #3
0
        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));
            }
        }
Beispiel #4
0
        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()));
        }
Beispiel #7
0
        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()));
            }
        }
Beispiel #8
0
        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);
        }
Beispiel #10
0
        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);
        }
Beispiel #11
0
        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);
        }
Beispiel #15
0
        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());
        }
Beispiel #16
0
 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()));
            }
        }