public async Task Distributor_Handles_Retries(HttpStatusCode failCode, bool shouldBeRetried, int?priority) { var firstCall = new ManualResetEvent(false); var secondCall = new ManualResetEvent(false); const string expectedRequestBody = "{ 'foo': 'bar' }"; var path = $"/{failCode}/{shouldBeRetried}/{priority ?? -1}"; var count = 0; var failedResponseReturned = false; string actualRequestBody = null; _httpSenderMock .Setup(x => x.SendAsync(It.IsAny <HttpRequestMessage>(), It.IsAny <CancellationToken>())) .Callback(async(HttpRequestMessage request, CancellationToken token) => { Log.LogInformation($"HTTP call {request.RequestUri} | count: {count}"); Assert.AreEqual(path, request.RequestUri.PathAndQuery); count++; if (count == 1) { firstCall.Set(); } else { secondCall.Set(); } actualRequestBody = await request.Content.ReadAsStringAsync(); }) .ReturnsAsync(() => { var response = !failedResponseReturned ? BuildResponse(failCode) : _okResponse; failedResponseReturned = true; return(response); }); // Fake popping the queue with a AC request envelope var requestEnvelope = await CreateRequestEnvelopeAsync(HttpMethod.Get, expectedRequestBody, path, null, priority); await Distributor.DistributeCall(requestEnvelope, _logger); Assert.IsTrue(firstCall.WaitOne(TimeSpan.FromSeconds(5)), "Expected a call to the Http Sender"); if (shouldBeRetried) { Assert.IsTrue(secondCall.WaitOne(TimeSpan.FromSeconds(5)), "Expected a second call to the Http Sender"); Assert.AreEqual(2, count, "The http sender should have been called twice"); } else { Assert.AreEqual(1, count, "The http sender should have been call once"); } Assert.AreEqual(expectedRequestBody, actualRequestBody, "The request body should survive being re-queued"); }
public async Task Distributor_Sends_Request(string method, int?priority) { const string expectedRequestBody = "{ 'foo': 'bar' }"; string actualRequestBody = null; _httpSenderMock .Setup(x => x.SendAsync(It.IsAny <HttpRequestMessage>(), It.IsAny <CancellationToken>())) .Callback(async(HttpRequestMessage request, CancellationToken token) => { actualRequestBody = await request.Content.ReadAsStringAsync(); }) .ReturnsAsync(_okResponse) .Verifiable(); var requestEnvelope = await CreateRequestEnvelopeAsync(new HttpMethod(method), expectedRequestBody, "/", null, priority); await Distributor.DistributeCall(requestEnvelope, _logger); _httpSenderMock.Verify(x => x.SendAsync(It.IsAny <HttpRequestMessage>(), It.IsAny <CancellationToken>()), Times.Once); Assert.AreEqual(expectedRequestBody, actualRequestBody); }
public async Task Distribution_Invocation_Logged_Verbose() { var logger = new LoggerFactory().CreateLogger(nameof(LogTests)); var mockLogger = new Mock <ISyncLogger>(); FulcrumApplication.Setup.SynchronousFastLogger = mockLogger.Object; var testDone = new ManualResetEvent(false); var origionalId = Guid.NewGuid().ToString(); var url = $"https://example.org/api/v1/stuffs/{origionalId}"; mockLogger .Setup(x => x.LogSync(It.IsAny <LogRecord>())) .Callback((LogRecord record) => { Console.WriteLine(record.Message); if (record.SeverityLevel == LogSeverityLevel.Verbose && record.Message.Contains(origionalId) && record.Message.Contains(url) && record.ToLogString().Contains("corr-id")) { testDone.Set(); } }); var callOut = new HttpRequestMessage(HttpMethod.Get, url); callOut.Headers.Add("X-Correlation-ID", "corr-id"); var requestEnvelope = new RawRequestEnvelope { Organization = Tenant.Organization, Environment = Tenant.Environment, OriginalRequestId = origionalId, RawRequest = await new Request { CallOut = callOut }.ToRawAsync() }; await Distributor.DistributeCall(requestEnvelope, logger); Assert.IsTrue(testDone.WaitOne(1000)); }
public async Task Distributor_Sends_Request_With_Callback(int?priority) { const string expectedRequestBody = "{ 'foo': 'bar' }"; string actualRequestBody = null; _httpSenderMock .Setup(x => x.SendAsync(It.Is((HttpRequestMessage request) => request.Method == HttpMethod.Get), It.IsAny <CancellationToken>())) .Callback(async(HttpRequestMessage request, CancellationToken token) => { actualRequestBody = await request.Content.ReadAsStringAsync(); }) .ReturnsAsync(_okResponse) .Verifiable(); var resetEvent = new ManualResetEvent(false); string callbackRequestBody = null; _httpSenderMock .Setup(x => x.SendAsync(It.Is((HttpRequestMessage request) => request.Method == HttpMethod.Post), It.IsAny <CancellationToken>())) .Callback(async(HttpRequestMessage request, CancellationToken token) => { callbackRequestBody = await request.Content.ReadAsStringAsync(); resetEvent.Set(); }) .ReturnsAsync(_okResponse) .Verifiable(); var requestEnvelope = await CreateRequestEnvelopeAsync(HttpMethod.Get, expectedRequestBody, "/", HttpMethod.Post, priority); await Distributor.DistributeCall(requestEnvelope, _logger); Assert.IsTrue(resetEvent.WaitOne(TimeSpan.FromSeconds(3))); _httpSenderMock.Verify(x => x.SendAsync(It.Is((HttpRequestMessage request) => request.Method == HttpMethod.Get), It.IsAny <CancellationToken>()), Times.Once); _httpSenderMock.Verify(x => x.SendAsync(It.Is((HttpRequestMessage request) => request.Method == HttpMethod.Post), It.IsAny <CancellationToken>()), Times.Once); Assert.AreEqual(expectedRequestBody, actualRequestBody); var callbackResponseContent = JsonConvert.DeserializeObject <ResponseContent>(callbackRequestBody); Assert.AreEqual(HttpStatusCode.OK, callbackResponseContent.StatusCode); Assert.AreEqual(OkContent, callbackResponseContent.Payload); Assert.AreEqual("application/json", callbackResponseContent.PayloadMediaType); }
/// <summary> /// Listens for messages on <see cref="MemoryQueue"/> and runs them through <see cref="Distributor"/>, simulating a QueueTrigger. /// </summary> private static void SimulateQueueTrigger(int?priority) { Task.Delay(TimeSpan.FromMilliseconds(100)).Wait(); ThreadHelper.FireAndForget(async() => { var queue = GetQueue(priority); Log.LogInformation($"Listening to queue '{queue}'"); while (_runBackgroundJob) { await Task.Delay(TimeSpan.FromMilliseconds(100)); Log.LogVerbose($"Checking for message on queue '{queue}'"); var message = queue.GetOneMessageNoBlock(); if (message == null) { continue; } var requestEnvelope = JsonConvert.DeserializeObject <RequestEnvelopeMock>(message); Log.LogInformation($"Popped '{queue.QueueName}' | {requestEnvelope.RawRequest.Title} | prio: '{requestEnvelope.RawRequest.Priority}' | attempts: {requestEnvelope.Attempts}"); await Distributor.DistributeCall(requestEnvelope, _logger); } Log.LogInformation($"Stopped listening to queue '{queue}'"); }); }