Пример #1
0
        async void TryReceiveNewMessage()
        {
            using (var operation = _parallelOperationsManager.TryBegin())
            {
                // if we didn't get to do our thing, pause the thread a very short while to avoid thrashing too much
                if (!operation.CanContinue())
                {
                    Thread.Sleep(10);
                    return;
                }

                using (var transactionContext = new DefaultTransactionContext())
                {
                    AmbientTransactionContext.Current = transactionContext;
                    try
                    {
                        var message = await TryReceiveTransportMessage(transactionContext);

                        if (message == null)
                        {
                            // no message: finish the tx and wait....
                            await transactionContext.Complete();

                            await _backoffStrategy.Wait();

                            return;
                        }

                        // we got a message, so we reset the backoff strategy
                        _backoffStrategy.Reset();

                        var context = new IncomingStepContext(message, transactionContext);

                        var stagedReceiveSteps = _pipeline.ReceivePipeline();

                        await _pipelineInvoker.Invoke(context, stagedReceiveSteps);

                        try
                        {
                            await transactionContext.Complete();
                        }
                        catch (Exception exception)
                        {
                            _log.Error(exception, "An error occurred when attempting to complete the transaction context");
                        }
                    }
                    catch (Exception exception)
                    {
                        // we should not end up here unless something is off....
                        _log.Error(exception, "Unhandled exception in thread worker - the pipeline didn't handle its own errors (this is bad)");
                        Thread.Sleep(100);
                    }
                    finally
                    {
                        AmbientTransactionContext.Current = null;
                    }
                }
            }
        }
Пример #2
0
        async void TryProcessMessage()
        {
            using (var op = _parallelOperationsManager.TryBegin())
            {
                if (!op.CanContinue())
                {
                    Thread.Sleep(10);
                    return;
                }

                using (var transactionContext = new DefaultTransactionContext())
                {
                    AmbientTransactionContext.Current = transactionContext;
                    try
                    {
                        var message = await _transport.Receive(transactionContext);

                        if (message == null)
                        {
                            // finish the tx and wait....
                            await transactionContext.Complete();

                            await _backoffHelper.Wait();

                            return;
                        }

                        _backoffHelper.Reset();

                        var context = new IncomingStepContext(message, transactionContext);
                        transactionContext.Items[StepContext.StepContextKey] = context;

                        var stagedReceiveSteps = _pipeline.ReceivePipeline();

                        await _pipelineInvoker.Invoke(context, stagedReceiveSteps);

                        await transactionContext.Complete();
                    }
                    catch (Exception exception)
                    {
                        _log.Error(exception, "Unhandled exception in thread worker");
                    }
                    finally
                    {
                        AmbientTransactionContext.Current = null;
                    }
                }
            }
        }
Пример #3
0
        async Task <List <string> > GetAll(ITransport input)
        {
            var transportMessages = new List <string>();
            var receivedNulls     = 0;

            while (receivedNulls < 5)
            {
                using (var transactionContext = new DefaultTransactionContext())
                {
                    var msg = await input.Receive(transactionContext, _cancellationToken);

                    if (msg != null)
                    {
                        transportMessages.Add(GetStringBody(msg));
                        await transactionContext.Complete();

                        continue;
                    }

                    await Task.Delay(100);

                    receivedNulls++;
                }
            }

            return(transportMessages);
        }
Пример #4
0
        public static async Task <TransportMessage> AwaitReceive(this ITransport transport, double timeoutSeconds = 5)
        {
            var stopwatch = Stopwatch.StartNew();
            var timeout   = TimeSpan.FromSeconds(timeoutSeconds);

            while (stopwatch.Elapsed < timeout)
            {
                TransportMessage receivedTransportMessage;

                using (var transactionContext = new DefaultTransactionContext())
                {
                    receivedTransportMessage = await transport.Receive(transactionContext);

                    await transactionContext.Complete();
                }

                if (receivedTransportMessage != null)
                {
                    return(receivedTransportMessage);
                }
            }

            throw new AssertionException(string.Format("Did not receive transport message from {0} within {1} timeout",
                                                       transport, timeout));
        }
Пример #5
0
        public async Task ReceivesNonExpiredMessage()
        {
            var queueName = TestConfig.QueueName("expiration");
            var transport = _factory.Create(queueName);
            var id        = Guid.NewGuid().ToString();

            using (var transactionContext = new DefaultTransactionContext())
            {
                var headers = new Dictionary <string, string>
                {
                    { "recognizzle", id }
                };
                await transport.Send(queueName, MessageWith(headers), transactionContext);

                await transactionContext.Complete();
            }

            await Task.Delay(5000);

            using (var transactionContext = new DefaultTransactionContext())
            {
                var transportMessage = await transport.Receive(transactionContext);

                await transactionContext.Complete();

                Assert.That(transportMessage, Is.Not.Null);

                var headers = transportMessage.Headers;

                Assert.That(headers.ContainsKey("recognizzle"));
                Assert.That(headers["recognizzle"], Is.EqualTo(id));
            }
        }
Пример #6
0
        public async Task ReceivesAlmostExpiredMessage()
        {
            var queueName = TestConfig.QueueName("expiration");
            var transport = _factory.Create(queueName);
            var id        = Guid.NewGuid().ToString();

            using (var transactionContext = new DefaultTransactionContext())
            {
                var headers = new Dictionary <string, string>
                {
                    { "recognizzle", id },
                    { Headers.TimeToBeReceived, "00:00:20" },
                    { Headers.SentTime, DateTimeOffset.UtcNow.ToString("O") }//< expires after 10 seconds!
                };
                await transport.Send(queueName, MessageWith(headers), transactionContext);

                await transactionContext.Complete();
            }

            await Task.Delay(3000);

            using (var transactionContext = new DefaultTransactionContext())
            {
                var transportMessage = await transport.Receive(transactionContext);

                await transactionContext.Complete();

                Assert.That(transportMessage, Is.Not.Null);
            }
        }
Пример #7
0
        async Task TimerElapsed()
        {
            using (var result = await _timeoutManager.GetDueMessages())
            {
                foreach (var dueMessage in result)
                {
                    var transportMessage = dueMessage.ToTransportMessage();
                    var returnAddress    = transportMessage.Headers[Headers.DeferredRecipient];

                    _log.Debug("Sending due message {0} to {1}",
                               transportMessage.Headers[Headers.MessageId],
                               returnAddress);

                    using (var context = new DefaultTransactionContext())
                    {
                        await _transport.Send(returnAddress, transportMessage, context);

                        await context.Complete();
                    }

                    await dueMessage.MarkAsCompleted();
                }

                await result.Complete();
            }
        }
Пример #8
0
        public async Task LotsOfAsyncStuffGoingDown(int numberOfMessages)
        {
            var receivedMessages = 0;
            var messageIds       = new ConcurrentDictionary <int, int>();

            Console.WriteLine("Sending {0} messages", numberOfMessages);

            await Task.WhenAll(Enumerable.Range(0, numberOfMessages)
                               .Select(async i =>
            {
                using (var context = new DefaultTransactionContext())
                {
                    await _transport.Send(QueueName, RecognizableMessage(i), context);
                    await context.Complete();

                    messageIds[i] = 0;
                }
            }));

            Console.WriteLine("Receiving {0} messages", numberOfMessages);

            using (var timer = new Timer(1000))
            {
                timer.Elapsed += delegate
                {
                    Console.WriteLine("Received: {0} msgs", receivedMessages);
                };
                timer.Start();

                await Task.WhenAll(Enumerable.Range(0, numberOfMessages)
                                   .Select(async i =>
                {
                    using (var context = new DefaultTransactionContext())
                    {
                        var msg = await _transport.Receive(context);
                        await context.Complete();

                        Interlocked.Increment(ref receivedMessages);

                        var id = int.Parse(msg.Headers["id"]);

                        messageIds.AddOrUpdate(id, 1, (_, existing) => existing + 1);
                    }
                }));

                await Task.Delay(1000);
            }

            Assert.That(messageIds.Keys.OrderBy(k => k).ToArray(), Is.EqualTo(Enumerable.Range(0, numberOfMessages).ToArray()));

            var kvpsDifferentThanOne = messageIds.Where(kvp => kvp.Value != 1).ToList();

            if (kvpsDifferentThanOne.Any())
            {
                Assert.Fail(@"Oh no! the following IDs were not received exactly once:

{0}",
                            string.Join(Environment.NewLine, kvpsDifferentThanOne.Select(kvp => string.Format("   {0}: {1}", kvp.Key, kvp.Value))));
            }
        }
Пример #9
0
        public static async Task <TransportMessage> WaitForNextMessage(this ITransport transport, int timeoutSeconds = 5)
        {
            var stopwatch = Stopwatch.StartNew();

            while (true)
            {
                using (var context = new DefaultTransactionContext())
                {
                    var nextMessage = await transport.Receive(context, new CancellationToken());

                    if (nextMessage != null)
                    {
                        return(nextMessage);
                    }

                    await context.Complete();
                }

                await Task.Delay(100);

                if (stopwatch.Elapsed < TimeSpan.FromSeconds(timeoutSeconds))
                {
                    continue;
                }

                throw new TimeoutException($"Did not receive message from transport with address '{transport.Address}' within {timeoutSeconds} s timeout");
            }
        }
Пример #10
0
        public static async Task <TransportMessage> AwaitReceive(this ITransport transport, double timeoutSeconds = 5)
        {
            var stopwatch = Stopwatch.StartNew();
            var timeout   = TimeSpan.FromSeconds(timeoutSeconds);
            var source    = new CancellationTokenSource();

            while (stopwatch.Elapsed < timeout)
            {
                TransportMessage receivedTransportMessage;

                using (var transactionContext = new DefaultTransactionContext())
                {
                    receivedTransportMessage = await transport.Receive(transactionContext, source.Token);

                    await transactionContext.Complete();
                }

                if (receivedTransportMessage != null)
                {
                    return(receivedTransportMessage);
                }
            }

            throw new AssertionException($"Did not receive transport message from {transport} within {timeout} timeout");
        }
Пример #11
0
        public async Task DoesNotReceiveExpiredMessage()
        {
            var queueName = TestConfig.QueueName("expiration");
            var transport = _factory.Create(queueName);
            var id        = Guid.NewGuid().ToString();

            using (var transactionContext = new DefaultTransactionContext())
            {
                var headers = new Dictionary <string, string>
                {
                    { Headers.MessageId, Guid.NewGuid().ToString() },
                    { "recognizzle", id },
                    { Headers.TimeToBeReceived, "00:00:04" } //< expires after 4 seconds!
                };
                await transport.Send(queueName, MessageWith(headers), transactionContext);

                await transactionContext.Complete();
            }

            await Task.Delay(5000);

            using (var transactionContext = new DefaultTransactionContext())
            {
                var transportMessage = await transport.Receive(transactionContext);

                await transactionContext.Complete();

                Assert.That(transportMessage, Is.Null);
            }
        }
Пример #12
0
        public async Task DoesNotReceiveExpiredMessage()
        {
            var queueName = TestConfig.GetName("expiration");
            var transport = _factory.Create(queueName);
            var id        = Guid.NewGuid().ToString();

            using (var transactionContext = new DefaultTransactionContext())
            {
                var headers = new Dictionary <string, string>
                {
                    { Headers.MessageId, Guid.NewGuid().ToString() },
                    { "recognizzle", id },
                    { Headers.TimeToBeReceived, "00:00:04" } //< expires after 4 seconds!
                };
                await transport.Send(queueName, MessageWith(headers), transactionContext);

                await transactionContext.Complete();
            }

            const int millisecondsDelay = 7000;

            var stopwatch = Stopwatch.StartNew();
            await Task.Delay(millisecondsDelay);

            Console.WriteLine($"Delay of {millisecondsDelay} ms actually lasted {stopwatch.ElapsedMilliseconds:0} ms");

            using (var transactionContext = new DefaultTransactionContext())
            {
                var transportMessage = await transport.Receive(transactionContext, _cancellationToken);

                await transactionContext.Complete();

                Assert.That(transportMessage, Is.Null);
            }
        }
Пример #13
0
        static List <int> SendMessages(int messageCount)
        {
            var transport = new MsmqTransport(QueueName, new ConsoleLoggerFactory(true));

            MsmqUtil.EnsureQueueExists(MsmqUtil.GetPath(QueueName));

            var sendIds = new List <int>();

            Enumerable.Range(0, messageCount)
            .Select(id => new SomeMessage {
                Id = id
            })
            .ToList()
            .ForEach(msg =>
            {
                using (var context = new DefaultTransactionContext())
                {
                    transport.Send(QueueName, TransportMessageHelpers.FromString(JsonConvert.SerializeObject(msg)),
                                   context).Wait();

                    context.Complete().Wait();

                    sendIds.Add(msg.Id);
                }
            });

            return(sendIds);
        }
        public void WorksWithPrefetch(int prefetch, int numberOfMessages)
        {
            var activator = Using(new BuiltinHandlerActivator());
            var counter   = new SharedCounter(numberOfMessages);

            Using(counter);

            activator.Handle <string>(async str =>
            {
                counter.Decrement();
            });

            Console.WriteLine("Sending {0} messages", numberOfMessages);

            var transport = GetTransport();
            var tasks     = Enumerable.Range(0, numberOfMessages)
                            .Select(i => string.Format("THIS IS MESSAGE # {0}", i))
                            .Select(async msg =>
            {
                using (var context = new DefaultTransactionContext())
                {
                    var headers          = DefaultHeaders();
                    var body             = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(msg));
                    var transportMessage = new TransportMessage(headers, body);

                    await transport.Send(_queueName, transportMessage, context);

                    await context.Complete();
                }
            })
                            .ToArray();

            Task.WhenAll(tasks).Wait();

            Console.WriteLine("Receiving {0} messages", numberOfMessages);

            var stopwatch = Stopwatch.StartNew();

            Configure.With(activator)
            .Transport(t =>
            {
                t.UseAzureServiceBus(StandardAzureServiceBusTransportFactory.ConnectionString, _queueName, _mode)
                .EnablePrefetching(prefetch);
            })
            .Options(o =>
            {
                o.SetNumberOfWorkers(5);
                o.SetMaxParallelism(10);
            })
            .Start();

            counter.WaitForResetEvent(timeoutSeconds: (int)(numberOfMessages * 0.1 + 3));

            var elapsedSeconds = stopwatch.Elapsed.TotalSeconds;

            Console.WriteLine("Receiving {0} messages took {1:0.0} s - that's {2:0.0} msg/s",
                              numberOfMessages, elapsedSeconds, numberOfMessages / elapsedSeconds);
        }
        void Send(string destinationAddress, string message)
        {
            Console.WriteLine("Sending to {0}", destinationAddress);

            using (var transactionContext = new DefaultTransactionContext())
            {
                _transport.Send(destinationAddress, NewMessage(message), transactionContext).Wait();
                transactionContext.Complete().Wait();
            }
        }
Пример #16
0
 public void Commit(Enlistment enlistment)
 {
     _transactionContext.Complete()
     .ContinueWith(_ =>
     {
         using (_transactionContext)
         {
             enlistment.Done();
         }
     });
 }
Пример #17
0
        async Task WithContext(Func <ITransactionContext, Task> contextAction, bool completeTransaction = true)
        {
            using (var context = new DefaultTransactionContext())
            {
                await contextAction(context);

                if (completeTransaction)
                {
                    await context.Complete();
                }
            }
        }
        string Receive()
        {
            using (var context = new DefaultTransactionContext())
            {
                var transportMessage = _transport.Receive(context, _cancellationToken).Result;

                context.Complete().Wait();

                if (transportMessage == null)
                {
                    return(null);
                }

                return(Encoding.UTF8.GetString(transportMessage.Body));
            }
        }
Пример #19
0
        public async Task ReceivesSentMessageWhenTransactionIsCommitted()
        {
            using (var context = new DefaultTransactionContext())
            {
                await _transport.Send(QueueName, RecognizableMessage(), context);

                await context.Complete();
            }

            using (var context = new DefaultTransactionContext())
            {
                var transportMessage = await _transport.Receive(context);

                await context.Complete();

                AssertMessageIsRecognized(transportMessage);
            }
        }
Пример #20
0
        async Task SendTransportMessage(string destinationAddress, TransportMessage transportMessage)
        {
            var transactionContext = GetCurrentTransactionContext(mustBelongToThisBus: true);

            if (transactionContext == null)
            {
                using (var context = new DefaultTransactionContext())
                {
                    await _transport.Send(destinationAddress, transportMessage, context);

                    await context.Complete();
                }
            }
            else
            {
                await _transport.Send(destinationAddress, transportMessage, transactionContext);
            }
        }
Пример #21
0
        async Task InnerSend(IEnumerable <string> destinationAddresses, Message logicalMessage)
        {
            var currentTransactionContext = GetCurrentTransactionContext(mustBelongToThisBus: true);

            if (currentTransactionContext != null)
            {
                await SendUsingTransactionContext(destinationAddresses, logicalMessage, currentTransactionContext);
            }
            else
            {
                using (var context = new DefaultTransactionContext())
                {
                    await SendUsingTransactionContext(destinationAddresses, logicalMessage, context);

                    await context.Complete();
                }
            }
        }
        public async Task ItWorks()
        {
            var gotMessage = new ManualResetEvent(false);

            _activator.Handle <string>(async str =>
            {
                Console.WriteLine("waiting 6 minutes....");

                // longer than the longest asb peek lock in the world...
                //await Task.Delay(TimeSpan.FromSeconds(3));
                await Task.Delay(TimeSpan.FromMinutes(6));

                Console.WriteLine("done waiting");

                gotMessage.Set();
            });

            await _bus.SendLocal("hej med dig min ven!");

            gotMessage.WaitOrDie(TimeSpan.FromMinutes(6.5));

            // shut down bus
            CleanUpDisposables();

            // see if queue is empty
            using (var transactionContext = new DefaultTransactionContext())
            {
                var message = await _transport.Receive(transactionContext, new CancellationTokenSource().Token);

                if (message != null)
                {
                    throw new AssertionException(
                              $"Did not expect to receive a message - got one with ID {message.Headers.GetValue(Headers.MessageId)}");
                }

                await transactionContext.Complete();
            }
        }
Пример #23
0
        async Task ProcessMessage(DefaultTransactionContext context, TransportMessage transportMessage)
        {
            try
            {
                context.Items["OwningBus"]        = _owningBus;
                AmbientTransactionContext.Current = 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.Current = null;
            }
        }
Пример #24
0
        public void Run()
        {
            Text.PrintLine("Will start receiving messages from '{0}'", InputQueue);

            if (DefaultOutputQueue != null)
            {
                Text.PrintLine("(will provide '{0}' as the default queue to forward messages to)", DefaultOutputQueue);
            }

            Text.PrintLine();

            while (true)
            {
                using (var transactionContext = new DefaultTransactionContext())
                {
                    var transportMessage = _transport.Receive(transactionContext).Result;

                    if (transportMessage == null)
                    {
                        break;
                    }

                    try
                    {
                        HandleMessage(transportMessage, transactionContext);

                        transactionContext.Complete().Wait();
                    }
                    catch (Exception exception)
                    {
                        Text.PrintLine("Failed: {0}", exception.Message);
                    }
                }

                Text.PrintLine("No more messages");
            }
        }
        public async void DoesntIgnoreDefinedTimeoutWhenReceiving(AzureServiceBusMode mode, int operationTimeoutInSeconds)
        {
            var operationTimeout = TimeSpan.FromSeconds(operationTimeoutInSeconds);

            var connString = StandardAzureServiceBusTransportFactory.ConnectionString;
            var builder    = new ServiceBusConnectionStringBuilder(connString)
            {
                OperationTimeout = operationTimeout
            };
            var newConnString = builder.ToString();

            var consoleLoggerFactory = new ConsoleLoggerFactory(false);
            var transport            = new AzureServiceBusTransport(newConnString, QueueName, consoleLoggerFactory, new TplAsyncTaskFactory(consoleLoggerFactory));

            Using(transport);

            transport.PurgeInputQueue();
            //Create the queue for the receiver since it cannot create it self beacuse of lacking rights on the namespace
            transport.CreateQueue(QueueName);

            var senderActivator = new BuiltinHandlerActivator();

            var senderBus = Configure.With(senderActivator)
                            .Transport(t => t.UseAzureServiceBus(newConnString, "sender", mode))
                            .Start();

            Using(senderBus);

            // queue 3 messages
            await senderBus.Advanced.Routing.Send(QueueName, "message to receiver");

            await senderBus.Advanced.Routing.Send(QueueName, "message to receiver2");

            await senderBus.Advanced.Routing.Send(QueueName, "message to receiver3");

            await Task.Delay(TimeSpan.FromSeconds(2)); // wait a bit to make sure the messages are queued.

            // receive 1
            using (var transactionContext = new DefaultTransactionContext())
            {
                var sw  = System.Diagnostics.Stopwatch.StartNew();
                var msg = await transport.Receive(transactionContext, _cancellationToken);

                sw.Stop();
                await transactionContext.Complete();

                msg.Should().NotBeNull();
                sw.Elapsed.Should().BeLessThan(TimeSpan.FromMilliseconds(1500));
            }

            // receive 2
            using (var transactionContext = new DefaultTransactionContext())
            {
                var sw  = System.Diagnostics.Stopwatch.StartNew();
                var msg = await transport.Receive(transactionContext, _cancellationToken);

                sw.Stop();
                await transactionContext.Complete();

                msg.Should().NotBeNull();
                sw.Elapsed.Should().BeLessThan(TimeSpan.FromMilliseconds(1500));
            }

            // receive 3
            using (var transactionContext = new DefaultTransactionContext())
            {
                var sw  = System.Diagnostics.Stopwatch.StartNew();
                var msg = await transport.Receive(transactionContext, _cancellationToken);

                sw.Stop();
                await transactionContext.Complete();

                msg.Should().NotBeNull();
                sw.Elapsed.Should().BeLessThan(TimeSpan.FromMilliseconds(1500));
            }

            // receive 4 - NOTHING
            using (var transactionContext = new DefaultTransactionContext())
            {
                var sw  = System.Diagnostics.Stopwatch.StartNew();
                var msg = await transport.Receive(transactionContext, _cancellationToken);

                sw.Stop();
                await transactionContext.Complete();

                msg.Should().BeNull();
                sw.Elapsed.Should().BeCloseTo(operationTimeout, 2000);
            }

            // put 1 more message
            await senderBus.Advanced.Routing.Send(QueueName, "message to receiver5");

            await Task.Delay(TimeSpan.FromSeconds(2)); // wait a bit to make sure the messages are queued.

            // receive 5
            using (var transactionContext = new DefaultTransactionContext())
            {
                var sw  = System.Diagnostics.Stopwatch.StartNew();
                var msg = await transport.Receive(transactionContext, _cancellationToken);

                sw.Stop();
                await transactionContext.Complete();

                msg.Should().NotBeNull();
                sw.Elapsed.Should().BeLessThan(TimeSpan.FromMilliseconds(1500));
            }

            // receive 6 - NOTHING
            using (var transactionContext = new DefaultTransactionContext())
            {
                var sw  = System.Diagnostics.Stopwatch.StartNew();
                var msg = await transport.Receive(transactionContext, _cancellationToken);

                sw.Stop();
                await transactionContext.Complete();

                msg.Should().BeNull();
                sw.Elapsed.Should().BeCloseTo(operationTimeout, 2000);
            }
        }
Пример #26
0
        async void TryReceiveNewMessage()
        {
            using (var operation = _parallelOperationsManager.TryBegin())
            {
                // if we didn't get to do our thing, let the OS decide what to do next.... we don't hog the processor
                if (!operation.CanContinue())
                {
                    Thread.Yield();
                    return;
                }

                using (var transactionContext = new DefaultTransactionContext())
                {
                    transactionContext.Items["CancellationToken"] = _cancellationTokenSource.Token;
                    transactionContext.Items["OwningBus"]         = _owningBus;
                    AmbientTransactionContext.Current             = transactionContext;
                    try
                    {
                        var result = await TryReceiveTransportMessage(transactionContext, _cancellationTokenSource.Token);

                        if (result.Exception != null)
                        {
                            if (result.Exception is TaskCanceledException || result.Exception is OperationCanceledException)
                            {
                                // this is normal - we're being shut down so we just return quickly
                                transactionContext.Dispose();
                                return;
                            }

                            _log.Warn("An error occurred when attempting to receive transport message: {0}", result.Exception);

                            // error: finish the tx and wait....
                            transactionContext.Dispose();

                            await _backoffStrategy.WaitError();

                            return;
                        }

                        var message = result.TransportMessage;
                        if (message == null)
                        {
                            // no message: finish the tx and wait....
                            await transactionContext.Complete();

                            transactionContext.Dispose();

                            await _backoffStrategy.Wait();

                            return;
                        }

                        // we got a message, so we reset the backoff strategy
                        _backoffStrategy.Reset();

                        var context            = new IncomingStepContext(message, transactionContext);
                        var stagedReceiveSteps = _pipeline.ReceivePipeline();

                        await _pipelineInvoker.Invoke(context, stagedReceiveSteps);

                        try
                        {
                            await transactionContext.Complete();
                        }
                        catch (Exception exception)
                        {
                            _log.Error(exception, "An error occurred when attempting to complete the transaction context");
                        }
                    }
                    catch (Exception exception)
                    {
                        // we should not end up here unless something is off....
                        _log.Error(exception, "Unhandled exception in thread worker - the pipeline didn't handle its own errors (this is bad)");
                        Thread.Sleep(100);
                    }
                    finally
                    {
                        AmbientTransactionContext.Current = null;
                    }
                }
            }
        }
Пример #27
0
        public void WorksWithPrefetch(int prefetch, int numberOfMessages)
        {
            AdjustLogging(LogLevel.Info);

            var activator        = new BuiltinHandlerActivator();
            var receivedMessages = 0;
            var done             = new ManualResetEvent(false);

            activator.Handle <string>(async str =>
            {
                Interlocked.Increment(ref receivedMessages);

                if (receivedMessages == numberOfMessages)
                {
                    done.Set();
                }
            });

            Console.WriteLine("Sending {0} messages", numberOfMessages);

            using (var transport = GetTransport())
            {
                var tasks = Enumerable.Range(0, numberOfMessages)
                            .Select(i => string.Format("THIS IS MESSAGE # {0}", i))
                            .Select(async msg =>
                {
                    using (var context = new DefaultTransactionContext())
                    {
                        var headers          = DefaultHeaders();
                        var body             = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(msg));
                        var transportMessage = new TransportMessage(headers, body);

                        await transport.Send(QueueName, transportMessage, context);

                        await context.Complete();
                    }
                })
                            .ToArray();

                Task.WhenAll(tasks).Wait();
            }

            Console.WriteLine("Receiving {0} messages", numberOfMessages);

            var stopwatch = Stopwatch.StartNew();

            using (Configure.With(activator)
                   .Transport(t =>
            {
                t.UseAzureServiceBus(AzureServiceBusTransportFactory.ConnectionString, QueueName)
                .EnablePrefetching(prefetch);
            })
                   .Options(o =>
            {
                o.SetNumberOfWorkers(5);
                o.SetMaxParallelism(10);
            })
                   .Start())
            {
                done.WaitOrDie(TimeSpan.FromSeconds(numberOfMessages * 0.1 + 3));
            }

            var elapsedSeconds = stopwatch.Elapsed.TotalSeconds;

            Console.WriteLine("Receiving {0} messages took {1:0.0} s - that's {2:0.0} msg/s",
                              numberOfMessages, elapsedSeconds, numberOfMessages / elapsedSeconds);
        }