예제 #1
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);
        }
예제 #2
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");
            }
        }
예제 #3
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();
            }
        }
예제 #4
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));
            }
        }
예제 #5
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))));
            }
        }
예제 #6
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);
            }
        }
예제 #7
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);
            }
        }
예제 #8
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);
            }
        }
예제 #9
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");
        }
예제 #10
0
        async void TryAsyncReceive(CancellationToken token, IDisposable parallelOperation)
        {
            try
            {
                using (parallelOperation)
                    using (var context = new DefaultTransactionContext())
                    {
                        var transportMessage = await ReceiveTransportMessage(token, context);

                        if (transportMessage == null)
                        {
                            context.Dispose();
                            parallelOperation.Dispose();
                            _backoffStrategy.Wait();
                            return;
                        }

                        _backoffStrategy.Reset();

                        await ProcessMessage(context, transportMessage);
                    }
            }
            catch (TaskCanceledException)
            {
                // it's fine - just a sign that we are shutting down
            }
            catch (OperationCanceledException)
            {
                // it's fine - just a sign that we are shutting down
            }
            catch (Exception exception)
            {
                _log.Error(exception, "Unhandled exception in thread pool worker");
            }
        }
예제 #11
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);
        }
예제 #12
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));
        }
예제 #13
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;
                    }
                }
            }
        }
        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 async Task ResolvingWithoutRegistrationYieldsEmptySequenec()
        {
            var handlerActivator = _factory.GetActivator();

            using (var transactionContext = new DefaultTransactionContext())
            {
                var handlers = (await handlerActivator.GetHandlers("hej", transactionContext)).ToList();

                Assert.That(handlers.Count, Is.EqualTo(0));
            }
        }
예제 #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();
                }
            }
        }
예제 #18
0
        public async Task CanRegisterHandler()
        {
            _factory.RegisterHandlerType <SomeStringHandler>();
            var handlerActivator = _factory.GetActivator();

            using (var transactionContext = new DefaultTransactionContext())
            {
                var handlers = (await handlerActivator.GetHandlers("hej", transactionContext)).ToList();

                Assert.That(handlers.Count, Is.EqualTo(1));
                Assert.That(handlers[0], Is.TypeOf <SomeStringHandler>());
            }
        }
예제 #19
0
        public void CanGetHandlerWithBusAndMessageContextArgument()
        {
            _activator.Register((bus, context) => new SomeHandler());

            using (var transactionContext = new DefaultTransactionContext())
            {
                AmbientTransactionContext.Current = transactionContext;

                var handlers = _activator.GetHandlers("hej med dig", transactionContext).Result;

                Assert.That(handlers.Single(), Is.TypeOf <SomeHandler>());
            }
        }
예제 #20
0
        public async Task ResolvesHandlersPolymorphically()
        {
            _factory.RegisterHandlerType <BaseMessageHandler>();

            var handlerActivator = _factory.GetActivator();

            using (var transactionContext = new DefaultTransactionContext())
            {
                var handlers = (await handlerActivator.GetHandlers(new DerivedMessage(), transactionContext)).ToList();

                Assert.That(handlers.Count, Is.EqualTo(1));
                Assert.That(handlers[0], Is.TypeOf <BaseMessageHandler>());
            }
        }
예제 #21
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;
                    }
                }
            }
        }
예제 #22
0
        async Task <TransportMessage> TryReceiveTransportMessage(DefaultTransactionContext transactionContext)
        {
            try
            {
                var message = await _transport.Receive(transactionContext);

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

                return(null);
            }
        }
        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));
            }
        }
예제 #24
0
        string GetInputQueueUrl()
        {
            try
            {
                using (var context = new DefaultTransactionContext())
                {
                    var inputQueueUrl = GetDestinationQueueUrlByName(Address, context);

                    return(inputQueueUrl);
                }
            }
            catch (Exception exception)
            {
                throw new RebusApplicationException(exception, $"Could not get URL of own input queue '{Address}'");
            }
        }
예제 #25
0
        public async Task DoesNotReceiveSentMessageWhenTransactionIsNotCommitted()
        {
            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);

                Assert.That(transportMessage, Is.Null);
            }
        }
예제 #26
0
        public void RegisterWorks()
        {
            var factory = new LightInjectContainerAdapterFactory();

            factory.RegisterHandlerType <SomeHandler>();
            factory.RegisterHandlerType <AnotherHandler>();

            using (var context = new DefaultTransactionContext())
            {
                const string stringMessage = "bimse";

                var handlers = factory.GetActivator().GetHandlers(stringMessage, context).Result.ToList();

                Assert.That(handlers.Count, Is.EqualTo(2));
            }
        }
예제 #27
0
        async Task <ReceiveResult> TryReceiveTransportMessage(DefaultTransactionContext transactionContext, CancellationToken cToken)
        {
            try
            {
                var message = await _transport.Receive(transactionContext, cToken);

                return(new ReceiveResult(message));
            }
            //catch (TaskCanceledException tex)
            //{
            //    return new ReceiveResult(tex, true);
            //}
            catch (Exception exception)
            {
                return(new ReceiveResult(exception));
            }
        }
예제 #28
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);
            }
        }
예제 #29
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();
                }
            }
        }
예제 #30
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);
            }
        }