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; } } } }
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; } } } }
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); }
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)); }
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)); } }
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); } }
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(); } }
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)))); } }
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"); } }
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"); }
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); } }
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); } }
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(); } }
public void Commit(Enlistment enlistment) { _transactionContext.Complete() .ContinueWith(_ => { using (_transactionContext) { enlistment.Done(); } }); }
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)); } }
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); } }
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); } }
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(); } }
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; } }
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); } }
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; } } } }
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); }