示例#1
0
        async Task ProcessMessage(TransactionContext context, TransportMessage transportMessage)
        {
            try
            {
                AmbientTransactionContext.SetCurrent(context);

                var stepContext = new IncomingStepContext(transportMessage, context);
                await _pipelineInvoker.Invoke(stepContext);

                try
                {
                    await context.Complete();
                }
                catch (Exception exception)
                {
                    _log.Error(exception, "An error occurred when attempting to complete the transaction context");
                }
            }
            catch (OperationCanceledException exception)
            {
                context.Abort();

                _log.Error(exception, "Worker was aborted while handling message {messageLabel}", transportMessage.GetMessageLabel());
            }
            catch (Exception exception)
            {
                context.Abort();

                _log.Error(exception, "Unhandled exception while handling message {messageLabel}", transportMessage.GetMessageLabel());
            }
            finally
            {
                AmbientTransactionContext.SetCurrent(null);
            }
        }
示例#2
0
        /// <summary>
        /// Invoke the receive side of the default
        /// pipeline with the passed message
        /// </summary>
        /// <param name="provider"></param>
        /// <param name="id"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        private static async Task Invoke(
            IServiceProvider provider,
            string id,
            object message
            )
        {
            var context = new FakeTransactionContext();

            var msg = new Message(
                new Dictionary <string, string>()
            {
                { Headers.MessageId, id }
            },
                message
                );

            var serializer = provider.GetService <ISerializer>();
            var invoker    = provider.GetService <IPipelineInvoker>();

            AmbientTransactionContext.SetCurrent(context);

            var transportMessage = await serializer.Serialize(msg);

            var ctx = new IncomingStepContext(transportMessage, context);

            await invoker.Invoke(ctx);

            context.Dispose();
        }
示例#3
0
        async Task TryProcessNextMessage()
        {
            var parallelOperation = _parallelOperationsManager.TryBegin();

            if (!parallelOperation.CanContinue())
            {
                await _backoffStrategy.WaitAsync(_cancellationToken);

                return;
            }

            try
            {
                using (parallelOperation)
                    using (var context = new TransactionContextWithOwningBus(_owningBus))
                    {
                        var transportMessage = await ReceiveTransportMessage(_cancellationToken, context);

                        if (transportMessage == null)
                        {
                            context.Dispose();

                            // get out quickly if we're shutting down
                            if (_cancellationToken.IsCancellationRequested || _busDisposalCancellationToken.IsCancellationRequested)
                            {
                                return;
                            }

                            // no need for another thread to rush in and discover that there is no message
                            //parallelOperation.Dispose();

                            await _backoffStrategy.WaitNoMessageAsync(_cancellationToken);

                            return;
                        }

                        _backoffStrategy.Reset();

                        try
                        {
                            AmbientTransactionContext.SetCurrent(context);
                            await ProcessMessage(context, transportMessage);
                        }
                        finally
                        {
                            AmbientTransactionContext.SetCurrent(null);
                        }
                    }
            }
            catch (OperationCanceledException) when(_cancellationToken.IsCancellationRequested || _busDisposalCancellationToken.IsCancellationRequested)
            {
                // we're shutting down
            }
            catch (Exception exception)
            {
                _log.Error(exception, "Unhandled exception in worker {workerName}", Name);
            }
        }
示例#4
0
        /// <summary>
        /// Extension method on <see cref="IBus"/> that allows for asynchronously publishing a request and dispatching
        /// the received reply to the continuation.
        /// </summary>
        /// <typeparam name="TReply">Specifies the expected type of the reply. Can be any type compatible with the actually received reply</typeparam>
        /// <param name="bus">The bus instance to use to publish the request</param>
        /// <param name="request">The request message</param>
        /// <param name="optionalHeaders">Headers to be included in the request message</param>
        /// <param name="timeout">Optionally specifies the max time to wait for a reply. If this time is exceeded, a <see cref="TimeoutException"/> is thrown</param>
        /// <param name="externalCancellationToken">An external cancellation token from some outer context that cancels waiting for a reply</param>
        /// <returns></returns>
        public static async Task <TReply> PublishRequest <TReply>(this IBus bus, object request, IDictionary <string, string> optionalHeaders = null, TimeSpan?timeout = null, CancellationToken externalCancellationToken = default)
        {
            var currentTransactionContext = AmbientTransactionContext.Current;

            try
            {
                AmbientTransactionContext.SetCurrent(null);
                return(await InnerProcessRequest <TReply>((eventMessage, headers) => bus.Publish(eventMessage, headers), request, optionalHeaders, timeout, externalCancellationToken));
            }
            finally
            {
                AmbientTransactionContext.SetCurrent(currentTransactionContext);
            }
        }
        /// <summary>
        /// Extension method on <see cref="IBus"/> that allows for asynchronously sending a request and dispatching
        /// the received reply to the continuation.
        /// </summary>
        /// <typeparam name="TReply">Specifies the expected type of the reply. Can be any type compatible with the actually received reply</typeparam>
        /// <param name="bus">The bus instance to use to send the request</param>
        /// <param name="request">The request message</param>
        /// <param name="optionalHeaders">Headers to be included in the request message</param>
        /// <param name="timeout">Optionally specifies the max time to wait for a reply. If this time is exceeded, a <see cref="TimeoutException"/> is thrown</param>
        /// <returns></returns>
        public static async Task <TReply> SendRequest <TReply>(this IBus bus, object request, Dictionary <string, string> optionalHeaders = null, TimeSpan?timeout = null)
        {
            var currentTransactionContext = AmbientTransactionContext.Current;

            try
            {
                AmbientTransactionContext.SetCurrent(null);
                return(await InnerSendRequest <TReply>(bus, request, optionalHeaders, timeout));
            }
            finally
            {
                AmbientTransactionContext.SetCurrent(currentTransactionContext);
            }
        }
示例#6
0
        public void DoesNotBlockOnCompletingTransactionContext()
        {
            var bus        = _activator.Bus.Advanced.SyncBus;
            var gotMessage = new ManualResetEvent(false);

            _activator.Handle <string>(async str => gotMessage.Set());

            using (var aspNet = new AspNetSimulatorSynchronizationContext())
            {
                aspNet.Post(s =>
                {
                    using (var context = new DefaultSyncTransactionContextScope())
                    {
                        var transactionContext = AmbientTransactionContext.Current;

                        try
                        {
                            // enlist some other async thing
                            transactionContext.OnCommitted(async() =>
                            {
                                Console.WriteLine("waiting....");
                                await Task.Delay(100);
                                Console.WriteLine("waiting....");
                                await Task.Delay(100);
                                Console.WriteLine("waiting....");
                                await Task.Delay(100);
                            });

                            // enlist an operation in the context
                            bus.SendLocal("HEJ MED DIG MIN VEN");

                            context.Complete();
                        }
                        finally
                        {
                            AmbientTransactionContext.SetCurrent(null);
                        }
                    }
                }, null);

                gotMessage.WaitOrDie(TimeSpan.FromSeconds(3));
            }
        }
示例#7
0
        async Task ProcessMessage(TransactionContext context, TransportMessage transportMessage)
        {
            try
            {
                context.Items["OwningBus"] = _owningBus;

                AmbientTransactionContext.SetCurrent(context);

                var incomingSteps = _pipeline.ReceivePipeline();
                var stepContext   = new IncomingStepContext(transportMessage, context);
                await _pipelineInvoker.Invoke(stepContext, incomingSteps);

                try
                {
                    await context.Complete();
                }
                catch (Exception exception)
                {
                    _log.Error(exception, "An error occurred when attempting to complete the transaction context");
                }
            }
            catch (ThreadAbortException exception)
            {
                context.Abort();

                _log.Error(exception, $"Worker was killed while handling message {transportMessage.GetMessageLabel()}");
            }
            catch (Exception exception)
            {
                context.Abort();

                _log.Error(exception, $"Unhandled exception while handling message {transportMessage.GetMessageLabel()}");
            }
            finally
            {
                AmbientTransactionContext.SetCurrent(null);
            }
        }
    protected override void TearDown()
    {
        AmbientTransactionContext.SetCurrent(null);

        _activator.Dispose();
    }