public virtual Task InvokeAsync <TMessage>(
            ConsumerDescriptor descriptor,
            IConsumer consumer,
            ConsumeContext <TMessage> envelope,
            CancellationToken cancelToken = default) where TMessage : class
        {
            var d           = descriptor;
            var p           = descriptor.WithEnvelope ? (object)envelope : envelope.Message;
            var fastInvoker = FastInvoker.GetInvoker(d.Method);
            var ct          = cancelToken;

            Task task;

            if (d.IsAsync && !d.FireForget)
            {
                // The all async case.
                ct   = _asyncRunner.CreateCompositeCancellationToken(cancelToken);
                task = ((Task)InvokeCore(null, ct));
                task.ContinueWith(t =>
                {
                    if (t.IsFaulted)
                    {
                        HandleException(t.Exception, d);
                    }
                }, TaskContinuationOptions.None);
            }
            else if (d.FireForget)
            {
                // Sync or Async without await. Needs new dependency scope.
                task = d.IsAsync
                    ? _asyncRunner.RunTask((scope, ct) => ((Task)InvokeCore(scope, ct)))
                    : _asyncRunner.Run((scope, ct) => InvokeCore(scope, ct));
                task.ConfigureAwait(false);
            }
            else
            {
                // The all sync case
                try
                {
                    InvokeCore(null, ct);
                }
                catch (Exception ex)
                {
                    HandleException(ex, d);
                }

                task = Task.CompletedTask;
            }

            return(task);

            object InvokeCore(IComponentContext c = null, CancellationToken cancelToken = default)
Esempio n. 2
0
        public void Invoke <TMessage>(ConsumerDescriptor descriptor, IConsumer consumer, ConsumeContext <TMessage> envelope) where TMessage : class
        {
            var d           = descriptor;
            var p           = descriptor.WithEnvelope ? (object)envelope : envelope.Message;
            var fastInvoker = FastInvoker.GetInvoker(d.Method);

            if (!d.FireForget && !d.IsAsync)
            {
                // The all synch case
                try
                {
                    InvokeCore();
                }
                catch (Exception ex)
                {
                    HandleException(ex, d);
                }
            }
            else if (!d.FireForget && d.IsAsync)
            {
                //// The awaitable Task case
                //BeginInvoke((Task)InvokeCore(cancelToken: AsyncRunner.AppShutdownCancellationToken), EndInvoke, d);

                // For now we must go with the AsyncRunner, the above call to BeginInvoke (APM > TPL) does not always
                // guarantee that the task is awaited and throws exceptions especially when EF is involved.
                using (var runner = AsyncRunner.Create())
                {
                    try
                    {
                        runner.Run((Task)InvokeCore(cancelToken: AsyncRunner.AppShutdownCancellationToken));
                    }
                    catch (Exception ex)
                    {
                        HandleException(ex, d);
                    }
                }
            }
            else if (d.FireForget && !d.IsAsync)
            {
                // A synch method should be executed async (without awaiting)
                AsyncRunner.Run((c, ct, state) => InvokeCore(c, ct), d)
                .ContinueWith(t => EndInvoke(t), /*TaskContinuationOptions.OnlyOnFaulted*/ TaskContinuationOptions.None)
                .ConfigureAwait(false);
            }
            else if (d.FireForget && d.IsAsync)
            {
                // An async (Task) method should be executed without awaiting
                AsyncRunner.Run((c, ct) => (Task)InvokeCore(c, ct), d)
                .ContinueWith(t => EndInvoke(t), TaskContinuationOptions.OnlyOnFaulted)
                .ConfigureAwait(false);
            }

            object InvokeCore(IComponentContext c = null, CancellationToken cancelToken = default(CancellationToken))
            {
                if (d.Parameters.Length == 0)
                {
                    // Only one method param: the message!
                    return(fastInvoker.Invoke(consumer, p));
                }

                var parameters = new object[d.Parameters.Length + 1];

                parameters[0] = p;

                int i = 0;

                foreach (var obj in ResolveParameters(c, d, cancelToken).ToArray())
                {
                    i++;
                    parameters[i] = obj;
                }

                return(fastInvoker.Invoke(consumer, parameters));
            }
        }
Esempio n. 3
0
        public void Invoke <TMessage>(ConsumerDescriptor descriptor, IConsumer consumer, ConsumeContext <TMessage> envelope) where TMessage : class
        {
            var d           = descriptor;
            var p           = descriptor.WithEnvelope ? (object)envelope : envelope.Message;
            var fastInvoker = FastInvoker.GetInvoker(d.Method);

            var items = HttpContext.Current.GetItem("ConsumerInvoker", () => new List <ConsumerDescriptor>());

            items.Add(d);

            if (!d.FireForget && !d.IsAsync)
            {
                // The all synch case
                try
                {
                    InvokeCore();
                }
                catch (Exception ex)
                {
                    HandleException(ex, d);
                }
            }
            else if (!d.FireForget && d.IsAsync)
            {
                // The awaitable Task case
                BeginInvoke((Task)InvokeCore(cancelToken: AsyncRunner.AppShutdownCancellationToken), EndInvoke, d);
            }
            else if (d.FireForget && !d.IsAsync)
            {
                // A synch method should be executed async (without awaiting)
                AsyncRunner.Run((c, ct, state) => InvokeCore(c, ct), d)
                .ContinueWith(t => EndInvoke(t), /*TaskContinuationOptions.OnlyOnFaulted*/ TaskContinuationOptions.None)
                .ConfigureAwait(false);
            }
            else if (d.FireForget && d.IsAsync)
            {
                // An async (Task) method should be executed without awaiting
                AsyncRunner.Run((c, ct) => (Task)InvokeCore(c, ct), d)
                .ContinueWith(t => EndInvoke(t), TaskContinuationOptions.OnlyOnFaulted)
                .ConfigureAwait(false);
            }

            object InvokeCore(IComponentContext c = null, CancellationToken cancelToken = default(CancellationToken))
            {
                if (d.Parameters.Length == 0)
                {
                    // Only one method param: the message!
                    return(fastInvoker.Invoke(consumer, p));
                }

                var parameters = new object[d.Parameters.Length + 1];

                parameters[0] = p;

                int i = 0;

                foreach (var obj in ResolveParameters(c, d, cancelToken).ToArray())
                {
                    i++;
                    parameters[i] = obj;
                }

                return(fastInvoker.Invoke(consumer, parameters));
            }
        }