public async Task Given_Valid_Request_And_Remote_Server_Listening_When_Sending_Then_Remote_Accepts() { var messageReceivedEvent = new ManualResetEvent(false); string content = null; var serverBaseUri = new UriBuilder { Scheme = "http", Host = "localhost", Port = 52180, Path = "/platibus.test/" }.Uri; var configuration = new HttpServerConfiguration { BaseUri = serverBaseUri }; configuration.AddHandlingRule<string>(".*", (c, ctx) => { content = c; messageReceivedEvent.Set(); ctx.Acknowledge(); }); bool messageReceived; using (var server = await HttpServer.Start(configuration)) { var endpoint = serverBaseUri; var message = new Message(new MessageHeaders { {HeaderName.ContentType, "text/plain"}, {HeaderName.MessageId, Guid.NewGuid().ToString()}, {HeaderName.Destination, endpoint.ToString()}, {HeaderName.MessageName, typeof (string).FullName}, }, "Hello, world!"); var transportService = await server.GetTransportService(); await transportService.SendMessage(message); messageReceived = await messageReceivedEvent .WaitOneAsync(TimeSpan.FromSeconds(3)); } // Sanity check. We're really testing the transport to ensure // that it doesn't throw. But if it does throw, then it would // be nice to get some info about how the server behaved. Assert.That(messageReceived, Is.True); Assert.That(content, Is.EqualTo("Hello, world!")); }
/// <summary> /// Observes the sent message replies until the first reply is received /// or a timeout occurs /// </summary> /// <param name="sentMessage">The sent message</param> /// <param name="timeout">The maximum amount of time to wait for a reply</param> /// <returns>Returns a task whose result will be the deserialized content of the /// reply message</returns> public static async Task<object> GetReply(this ISentMessage sentMessage, TimeSpan timeout = default(TimeSpan)) { object reply = null; using (var replyReceivedEvent = new ManualResetEvent(false)) using (sentMessage.ObserveReplies().Subscribe(r => { reply = r; // ReSharper disable once AccessToDisposedClosure replyReceivedEvent.Set(); })) { await replyReceivedEvent.WaitOneAsync(timeout); } return reply; }
public async Task Given_Existing_Queue_When_New_Message_Queued_Then_Listener_Should_Fire() { var listenerCalledEvent = new ManualResetEvent(false); var queueName = new QueueName(Guid.NewGuid().ToString()); var rmqQueueingService = new RabbitMQMessageQueueingService(RabbitMQUri); try { var mockListener = new Mock<IQueueListener>(); mockListener.Setup( x => x.MessageReceived(It.IsAny<Message>(), It.IsAny<IQueuedMessageContext>(), It.IsAny<CancellationToken>())) .Callback<Message, IQueuedMessageContext, CancellationToken>((msg, ctx, ct) => { ctx.Acknowledge(); listenerCalledEvent.Set(); }) .Returns(Task.FromResult(true)); await rmqQueueingService.CreateQueue(queueName, mockListener.Object, new QueueOptions {MaxAttempts = 1}); var message = new Message(new MessageHeaders { {HeaderName.ContentType, "text/plain"}, {HeaderName.MessageId, Guid.NewGuid().ToString()} }, "Hello, world!"); await rmqQueueingService.EnqueueMessage(queueName, message, Thread.CurrentPrincipal); await listenerCalledEvent.WaitOneAsync(TimeSpan.FromSeconds(1)); var messageEqualityComparer = new MessageEqualityComparer(); mockListener.Verify( x => x.MessageReceived(It.Is<Message>(m => messageEqualityComparer.Equals(m, message)), It.IsAny<IQueuedMessageContext>(), It.IsAny<CancellationToken>()), Times.Once()); Assert.That(GetQueueDepth(queueName), Is.EqualTo(0)); Assert.That(GetQueueDepth(queueName.GetRetryQueueName()), Is.EqualTo(0)); } finally { rmqQueueingService.Dispose(); DeleteQueue(queueName); } }
public async Task When_New_Message_Queued_Then_Listener_Should_Fire() { var listenerCalledEvent = new ManualResetEvent(false); var connectionStringSettings = GetConnectionStringSettings(); var sqlQueueingService = new SQLMessageQueueingService(connectionStringSettings); sqlQueueingService.Init(); var mockListener = new Mock<IQueueListener>(); mockListener.Setup( x => x.MessageReceived(It.IsAny<Message>(), It.IsAny<IQueuedMessageContext>(), It.IsAny<CancellationToken>())) .Callback<Message, IQueuedMessageContext, CancellationToken>((msg, ctx, ct) => { ctx.Acknowledge(); listenerCalledEvent.Set(); }) .Returns(Task.FromResult(true)); var queueName = new QueueName(Guid.NewGuid().ToString()); await sqlQueueingService.CreateQueue(queueName, mockListener.Object, new QueueOptions {MaxAttempts = 1}); var message = new Message(new MessageHeaders { {HeaderName.ContentType, "text/plain"}, {HeaderName.MessageId, Guid.NewGuid().ToString()} }, "Hello, world!"); await sqlQueueingService.EnqueueMessage(queueName, message, Thread.CurrentPrincipal); await listenerCalledEvent.WaitOneAsync(TimeSpan.FromSeconds(1)); var messageEqualityComparer = new MessageEqualityComparer(); mockListener.Verify( x => x.MessageReceived(It.Is<Message>(m => messageEqualityComparer.Equals(m, message)), It.IsAny<IQueuedMessageContext>(), It.IsAny<CancellationToken>()), Times.Once()); }
public async Task Given_Message_When_Sending_Then_Reply_Should_Be_Observed() { await With.RabbitMQHostedBusInstances(async (platibus0, platibus1) => { var replyReceivedEvent = new ManualResetEvent(false); var repliesCompletedEvent = new ManualResetEvent(false); var replies = new ConcurrentQueue<object>(); var message = new TestMessage { GuidData = Guid.NewGuid(), IntData = RNG.Next(0, int.MaxValue), StringData = "Hello, world!", DateData = DateTime.UtcNow }; var sentMessage = await platibus0.Send(message); var subscription = sentMessage .ObserveReplies() .Subscribe(r => { replies.Enqueue(r); replyReceivedEvent.Set(); }, () => repliesCompletedEvent.Set()); var replyReceived = await replyReceivedEvent.WaitOneAsync(TimeSpan.FromSeconds(30)); var repliesCompleted = await repliesCompletedEvent.WaitOneAsync(TimeSpan.FromSeconds(30)); subscription.Dispose(); Assert.That(replyReceived, Is.True); Assert.That(repliesCompleted, Is.True); Assert.That(replies.Count, Is.EqualTo(1)); var reply = replies.First(); Assert.That(reply, Is.InstanceOf<TestReply>()); }); }
public async Task Given_Queued_Message_When_Context_Acknowledged_Then_Message_Should_Be_Acknowledged() { var listenerCalledEvent = new ManualResetEvent(false); var connectionStringSettings = GetConnectionStringSettings(); var queueName = new QueueName(Guid.NewGuid().ToString()); var sqlQueueingService = new SQLMessageQueueingService(connectionStringSettings); sqlQueueingService.Init(); var mockListener = new Mock<IQueueListener>(); mockListener.Setup( x => x.MessageReceived(It.IsAny<Message>(), It.IsAny<IQueuedMessageContext>(), It.IsAny<CancellationToken>())) .Callback<Message, IQueuedMessageContext, CancellationToken>((msg, ctx, ct) => { ctx.Acknowledge(); listenerCalledEvent.Set(); }) .Returns(Task.FromResult(true)); await sqlQueueingService.CreateQueue(queueName, mockListener.Object, new QueueOptions {MaxAttempts = 1}); var message = new Message(new MessageHeaders { {HeaderName.ContentType, "text/plain"}, {HeaderName.MessageId, Guid.NewGuid().ToString()} }, "Hello, world!"); await sqlQueueingService.EnqueueMessage(queueName, message, Thread.CurrentPrincipal); await listenerCalledEvent.WaitOneAsync(TimeSpan.FromSeconds(1)); // The listener is called before the row is updated, so there is a possible // race condition here. Wait for a second to allow the update to take place // before enumerating the rows to see that they were actually deleted. await Task.Delay(TimeSpan.FromSeconds(1)); var messageEqualityComparer = new MessageEqualityComparer(); mockListener.Verify( x => x.MessageReceived(It.Is<Message>(m => messageEqualityComparer.Equals(m, message)), It.IsAny<IQueuedMessageContext>(), It.IsAny<CancellationToken>()), Times.Once()); var sqlQueueInspector = new SQLMessageQueueInspector(sqlQueueingService, queueName); var queuedMessages = (await sqlQueueInspector.EnumerateMessages()).ToList(); Assert.That(queuedMessages, Is.Empty); }
public async Task Given_Auto_Acknowledge_Queue_When_Listener_Throws_Then_Message_Should_Not_Be_Acknowledged() { var listenerCalledEvent = new ManualResetEvent(false); var connectionStringSettings = GetConnectionStringSettings(); var queueName = new QueueName(Guid.NewGuid().ToString()); var sqlQueueingService = new SQLMessageQueueingService(connectionStringSettings); sqlQueueingService.Init(); var mockListener = new Mock<IQueueListener>(); mockListener.Setup(x => x.MessageReceived(It.IsAny<Message>(), It.IsAny<IQueuedMessageContext>(), It.IsAny<CancellationToken>())) .Callback<Message, IQueuedMessageContext, CancellationToken>((msg, ctx, ct) => { listenerCalledEvent.Set(); throw new Exception(); }); await sqlQueueingService .CreateQueue(queueName, mockListener.Object, new QueueOptions { AutoAcknowledge = true, MaxAttempts = 2, // So the message doesn't get moved to the DLQ RetryDelay = TimeSpan.FromSeconds(30) }); var message = new Message(new MessageHeaders { {HeaderName.ContentType, "text/plain"}, {HeaderName.MessageId, Guid.NewGuid().ToString()} }, "Hello, world!"); await sqlQueueingService.EnqueueMessage(queueName, message, Thread.CurrentPrincipal); var listenerCalled = await listenerCalledEvent .WaitOneAsync(Debugger.IsAttached ? TimeSpan.FromMinutes(5) : TimeSpan.FromSeconds(3)); Assert.That(listenerCalled, Is.True); // The listener is called before the row is updated, so there is a possible // race condition here. Wait for a second to allow the update to take place // before enumerating the rows to see that they were actually not updated. await Task.Delay(TimeSpan.FromSeconds(1)); var messageEqualityComparer = new MessageEqualityComparer(); mockListener.Verify(x => x.MessageReceived(It.Is<Message>(m => messageEqualityComparer.Equals(m, message)), It.IsAny<IQueuedMessageContext>(), It.IsAny<CancellationToken>()), Times.Once()); var sqlQueueInspector = new SQLMessageQueueInspector(sqlQueueingService, queueName); var queuedMessages = (await sqlQueueInspector.EnumerateMessages()).ToList(); Assert.That(queuedMessages[0].Message, Is.EqualTo(message).Using(messageEqualityComparer)); }
public async Task Given_Queued_Message_When_Acknowledged_Then_Message_Should_Be_Deleted() { var listenerCalledEvent = new ManualResetEvent(false); var tempDir = GetTempDirectory(); var queueName = new QueueName(Guid.NewGuid().ToString()); var queuePath = Path.Combine(tempDir.FullName, queueName); var queueDir = new DirectoryInfo(queuePath); if (!queueDir.Exists) { queueDir.Create(); } var fsQueueingService = new FilesystemMessageQueueingService(tempDir); fsQueueingService.Init(); var mockListener = new Mock<IQueueListener>(); mockListener.Setup( x => x.MessageReceived(It.IsAny<Message>(), It.IsAny<IQueuedMessageContext>(), It.IsAny<CancellationToken>())) .Callback<Message, IQueuedMessageContext, CancellationToken>((msg, ctx, ct) => { ctx.Acknowledge(); listenerCalledEvent.Set(); }) .Returns(Task.FromResult(true)); await fsQueueingService.CreateQueue(queueName, mockListener.Object, new QueueOptions {MaxAttempts = 1}); var message = new Message(new MessageHeaders { {HeaderName.ContentType, "text/plain"}, {HeaderName.MessageId, Guid.NewGuid().ToString()} }, "Hello, world!"); await fsQueueingService.EnqueueMessage(queueName, message, Thread.CurrentPrincipal); await listenerCalledEvent.WaitOneAsync(TimeSpan.FromSeconds(1)); // The listener is called before the file is deleted, so there is a possible // race condition here. Wait for a second to allow the delete to take place // before enumerating the files to see that they were actually deleted. await Task.Delay(TimeSpan.FromSeconds(1)); var messageEqualityComparer = new MessageEqualityComparer(); mockListener.Verify( x => x.MessageReceived(It.Is<Message>(m => messageEqualityComparer.Equals(m, message)), It.IsAny<IQueuedMessageContext>(), It.IsAny<CancellationToken>()), Times.Once()); var queuedMessages = queueDir.EnumerateFiles() .Select(f => new MessageFile(f)) .ToList(); Assert.That(queuedMessages, Is.Empty); }
public async Task Given_Existing_Message_When_Creating_Queue_Then_Listener_Should_Fire() { var listenerCalledEvent = new ManualResetEvent(false); var tempDir = GetTempDirectory(); var queueName = new QueueName(Guid.NewGuid().ToString()); var queuePath = Path.Combine(tempDir.FullName, queueName); var queueDir = new DirectoryInfo(queuePath); if (!queueDir.Exists) { queueDir.Create(); } var message = new Message(new MessageHeaders { {HeaderName.ContentType, "text/plain"}, {HeaderName.MessageId, Guid.NewGuid().ToString()} }, "Hello, world!"); await MessageFile.Create(queueDir, message, Thread.CurrentPrincipal); var fsQueueingService = new FilesystemMessageQueueingService(tempDir); fsQueueingService.Init(); var mockListener = new Mock<IQueueListener>(); mockListener.Setup( x => x.MessageReceived(It.IsAny<Message>(), It.IsAny<IQueuedMessageContext>(), It.IsAny<CancellationToken>())) .Callback<Message, IQueuedMessageContext, CancellationToken>((msg, ctx, ct) => { ctx.Acknowledge(); listenerCalledEvent.Set(); }) .Returns(Task.FromResult(true)); await fsQueueingService.CreateQueue(queueName, mockListener.Object, new QueueOptions {MaxAttempts = 1}); await listenerCalledEvent.WaitOneAsync(TimeSpan.FromSeconds(1)); var messageEqualityComparer = new MessageEqualityComparer(); mockListener.Verify( x => x.MessageReceived(It.Is<Message>(m => messageEqualityComparer.Equals(m, message)), It.IsAny<IQueuedMessageContext>(), It.IsAny<CancellationToken>()), Times.Once()); }
public async Task Given_Existing_Message_When_Creating_Queue_Then_Listener_Should_Fire() { var listenerCalledEvent = new ManualResetEvent(false); var baseDirectory = GetTempDirectory(); var queueName = new QueueName(Guid.NewGuid().ToString()); var message = new Message(new MessageHeaders { {HeaderName.ContentType, "text/plain"}, {HeaderName.MessageId, Guid.NewGuid().ToString()} }, "Hello, world!"); var sqlQueueingService = new SQLiteMessageQueueingService(baseDirectory); sqlQueueingService.Init(); // Insert a test message before creating queue var sqlQueueInspector = new SQLiteMessageQueueInspector(baseDirectory, queueName); await sqlQueueInspector.InsertMessage(message, Thread.CurrentPrincipal); var mockListener = new Mock<IQueueListener>(); mockListener.Setup(x => x.MessageReceived(It.IsAny<Message>(), It.IsAny<IQueuedMessageContext>(), It.IsAny<CancellationToken>())) .Callback<Message, IQueuedMessageContext, CancellationToken>((msg, ctx, ct) => { ctx.Acknowledge(); listenerCalledEvent.Set(); }) .Returns(Task.FromResult(true)); // Create the queue, which should trigger the inserted message to be enqueued // and processed await sqlQueueingService.CreateQueue(queueName, mockListener.Object, new QueueOptions {MaxAttempts = 1}); await listenerCalledEvent.WaitOneAsync(TimeSpan.FromSeconds(1)); var messageEqualityComparer = new MessageEqualityComparer(); mockListener.Verify(x => x.MessageReceived(It.Is<Message>(m => messageEqualityComparer.Equals(m, message)), It.IsAny<IQueuedMessageContext>(), It.IsAny<CancellationToken>()), Times.Once()); }
public async Task Given_Auto_Acknowledge_Queue_When_Not_Acknowledged_Then_Message_Should_Be_Deleted() { var queueName = new QueueName(Guid.NewGuid().ToString()); var rmqQueueingService = new RabbitMQMessageQueueingService(RabbitMQUri); try { var listenerCalledEvent = new ManualResetEvent(false); var mockListener = new Mock<IQueueListener>(); mockListener.Setup(x => x.MessageReceived(It.IsAny<Message>(), It.IsAny<IQueuedMessageContext>(), It.IsAny<CancellationToken>())) .Callback<Message, IQueuedMessageContext, CancellationToken>( (msg, ctx, ct) => { listenerCalledEvent.Set(); }) .Returns(Task.FromResult(true)); await rmqQueueingService.CreateQueue(queueName, mockListener.Object, new QueueOptions {AutoAcknowledge = true}); var message = new Message(new MessageHeaders { {HeaderName.ContentType, "text/plain"}, {HeaderName.MessageId, Guid.NewGuid().ToString()} }, "Hello, world!"); await rmqQueueingService.EnqueueMessage(queueName, message, Thread.CurrentPrincipal); await listenerCalledEvent.WaitOneAsync(TimeSpan.FromSeconds(1)); // The listener is called before the file is deleted, so there is a possible // race condition here. Wait for a second to allow the delete to take place // before enumerating the files to see that they were actually deleted. await Task.Delay(TimeSpan.FromSeconds(1)); var messageEqualityComparer = new MessageEqualityComparer(); mockListener.Verify(x => x.MessageReceived(It.Is<Message>(m => messageEqualityComparer.Equals(m, message)), It.IsAny<IQueuedMessageContext>(), It.IsAny<CancellationToken>()), Times.Once()); Assert.That(GetQueueDepth(queueName), Is.EqualTo(0)); Assert.That(GetQueueDepth(queueName.GetRetryQueueName()), Is.EqualTo(0)); } finally { rmqQueueingService.Dispose(); DeleteQueue(queueName); } }