public async Task <ActionResult <EnqueueResponse> > Post(EnqueueRequest request) { if (request.ExecuteOn.HasValue && request.ExecuteOn < DateTime.UtcNow) { return(StatusCode(500, new ApiResponse { Success = false, ErrorMessage = "ExecuteOn must either be null for immidiate execution or a time (UTC) in the future." })); } try { var queueItem = await queueItemRepository.InsertQueueItem(request.QueueName, request.Payload, request.ExecuteOn, request.UniqueKey); var response = new EnqueueResponse() { Success = true, CreateDate = queueItem.CreateDate, State = queueItem.State.ToString("g"), UniqueKey = queueItem.UniqueKey }; return(Ok(response)); } catch (Exception ex) { var executeAfter = request.ExecuteOn.HasValue ? request.ExecuteOn.Value.ToString("yyyy-MM-dd HH:mm:ss") : "Now"; logger.LogError(ex, $"Failed to enqueue into worker/queue: '{request.QueueName}' with unique key: '{request.UniqueKey ?? "No unique key set"}' to be executed after: '{executeAfter}' with payload: {request.Payload}"); return(StatusCode(500, new ApiResponse { Success = false, ErrorMessage = ex.Message })); } }
/// <inheritdoc/> public IObservable <QueuedStoreDto> Enqueue(EnqueueRequest enqueueRequest, FunctionParameters parameters) => Observable.Return(new QueuedStoreDto { Store = enqueueRequest.Store, User = new UserDto { Id = enqueueRequest.UserId }, RemainingQueueTime = DateTimeOffset.Now.AddHours(1.5) });
/// <summary> /// Enqueues a new task to be handled /// </summary> /// <param name="message"> /// The message to enqueue, this is probable some sort of serialized blob of /// whatever task format you prefer /// </param> /// <param name="priority">The priority of the task</param> /// <param name="requiredCapabilities">The capabilities required to complete the task</param> /// <returns>A guid of the created task</returns> public async Task <Guid> EnqueueRequestAsync(byte[] message, Priority priority, IEnumerable <string> requiredCapabilities) { var request = new EnqueueRequest { Message = ByteString.CopyFrom(message), Priority = priority }; request.RequiredCapabilities.AddRange(requiredCapabilities); var wrapper = new RequestWrapper { Enqueue = request }; var responseWrapper = await ExecuteRequest(wrapper, ResponseWrapper.MessageOneofCase.Enqueue); var response = responseWrapper.Enqueue; return(Guid.Parse(response.Id)); }
public async Task RetryOnFailure() { // ARRANGE var handlerMock = new Mock <HttpMessageHandler>(MockBehavior.Strict); handlerMock .Protected() // Setup the PROTECTED method to mock .Setup <Task <HttpResponseMessage> >( "SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>() ) // prepare the expected response of the mocked http call .ReturnsAsync(new HttpResponseMessage() { StatusCode = HttpStatusCode.BadRequest, Content = new StringContent("{'State':'processing'}"), }) .Verifiable(); // use real http client with mocked handler here var httpClient = new HttpClient(handlerMock.Object) { BaseAddress = new Uri("http://no-valid-url.com/"), }; var settings = new QueueApiConfig() { Key = "fakeKey", Secret = "fakeSecret", Retries = 3, RetryDelay = 3 }; IOptions <QueueApiConfig> appSettingsOptions = Options.Create(settings); var loggerMock = new Mock <ILogger <QueueApiClient> >(); var subjectUnderTest = new QueueApiClient(httpClient, loggerMock.Object, appSettingsOptions); var request = new EnqueueRequest() { QueueName = "FakeQueue", Payload = "{'fakePayload':'fakevalue'}" }; // ACT await Assert.ThrowsExceptionAsync <EnqueueFailedException>(() => subjectUnderTest.EnqueueAsync(request)); // ASSERT // also check the 'http' call was like we expected it var expectedUri = new Uri("http://no-valid-url.com/queue"); handlerMock.Protected().Verify( "SendAsync", Times.Exactly(4), // one original call + 3 retries ItExpr.Is <HttpRequestMessage>(req => req.Method == HttpMethod.Post && // we expected a POST request req.RequestUri == expectedUri // to this uri ), ItExpr.IsAny <CancellationToken>() ); }