public async Task ThenExecuteStepWithReceivingPModeAsync() { // Arrange var entity = new InMessage($"error-{Guid.NewGuid()}"); entity.InitializeIdFromDatabase(1); var fixture = new MessagingContext( EmptyNotifyMessageEnvelope(Status.Error), new ReceivedEntityMessage(entity)) { SendingPMode = new SendingProcessingMode { ErrorHandling = { NotifyMethod = new LocationMethod("not-empty-location") } } }; GetDataStoreContext.InsertInMessage(new InMessage($"entity-{Guid.NewGuid()}")); var spySender = new SpySender(); IStep sut = CreateSendNotifyStepWithSender(spySender); // Act await sut.ExecuteAsync(fixture); // Assert Assert.True(spySender.IsNotified); }
public async Task ThenExecuteStepFailsWithFailedSenderAsync() { // Arrange DeliverMessageEnvelope envelope = EmptyDeliverMessageEnvelope(); IStep sut = CreateSendDeliverStepWithSender(new SaboteurSender()); // Act await Assert.ThrowsAnyAsync <Exception>(() => sut.ExecuteAsync(new MessagingContext(envelope))); }
public async Task ThenExecuteStepFailsWithConnectionFailureAsync() { // Arrange IStep sut = CreateSendNotifyStepWithSender(new SaboteurSender()); var fixture = new MessagingContext( EmptyNotifyMessageEnvelope(Status.Delivered)); // Act / Assert await Assert.ThrowsAnyAsync <Exception>( () => sut.ExecuteAsync(fixture)); }
/// <summary> /// Run the selected step /// </summary> /// <param name="messagingContext"></param> /// <returns></returns> public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext) { if (_condition(messagingContext)) { IStep steps = StepBuilder.FromSettings(_thenSteps).BuildAsSingleStep(); return(await steps.ExecuteAsync(messagingContext).ConfigureAwait(false)); } else { IStep steps = StepBuilder.FromSettings(_elseSteps).BuildAsSingleStep(); return(await steps.ExecuteAsync(messagingContext).ConfigureAwait(false)); } }
public async Task Send_Returns_Empty_Response_For_Empty_Request_For_Response_SendPMode() { // Arrange IStep sut = CreateSendStepWithResponse( StubHttpClient.ThatReturns(HttpStatusCode.Accepted)); MessagingContext ctx = CreateMessagingContextWithDefaultPullRequest(); ctx.SendingPMode = CreateSendPModeWithPushUrl(); // Act StepResult actualResult = await sut.ExecuteAsync(ctx); // Assert Assert.True(actualResult.MessagingContext.AS4Message.IsEmpty); Assert.False(actualResult.CanProceed); }
public async Task Send_Results_In_Stop_Execution_If_Response_Is_PullRequest_Warning_For_Exsisting_SendPMode() { // Arrange AS4Message as4Message = AS4Message.Create(Error.CreatePullRequestWarning($"error-{Guid.NewGuid()}")); IStep sut = CreateSendStepWithResponse( StubHttpClient.ThatReturns(as4Message)); MessagingContext ctx = CreateMessagingContextWithDefaultPullRequest(); ctx.SendingPMode = CreateSendPModeWithPushUrl(); // Act StepResult actualResult = await sut.ExecuteAsync(ctx); // Assert Assert.False(actualResult.CanProceed); }
private async Task RunStartupSteps(IList <string> steps, string processorName) { foreach (string stepName in steps) { IStep step = registry.GetStep(stepName); ExecutionStatus status = step.ParallelCount == null || step.ParallelCount < 2 ? await step.ExecuteAsync().ConfigureAwait(false) : await ExcuteStepInParallel(processorName, stepName, step).ConfigureAwait(false); if (status != ExecutionStatus.Success) { log.LogCritical("{Step} experienced an error in startup processor {Processor}", stepName, processorName); throw new InvalidOperationException($"Startup processor {processorName} encountered an error"); } } }
public async Task ThenExecuteStepSucceedsWithValidSenderAsync() { // Arrange DeliverMessageEnvelope envelope = EmptyDeliverMessageEnvelope(); var spySender = new Mock <IDeliverSender>(); spySender.Setup(s => s.SendAsync(envelope)) .ReturnsAsync(SendResult.Success); IStep sut = CreateSendDeliverStepWithSender(spySender.Object); // Act await sut.ExecuteAsync(new MessagingContext(envelope) { ReceivingPMode = CreateDefaultReceivingPMode() }); // Assert spySender.Verify(s => s.SendAsync(It.IsAny <DeliverMessageEnvelope>()), Times.Once); }
public async Task Update_RetryReliability_To_Pending_When_Receiver_Is_Offline() { // Arrange string ebmsMessageId = $"user-{Guid.NewGuid()}"; AS4Message tobeSendMessage = AS4Message.Create(new UserMessage(ebmsMessageId)); var outMessage = new OutMessage(ebmsMessageId); GetDataStoreContext.InsertOutMessage(outMessage); GetDataStoreContext.InsertRetryReliability( RetryReliability.CreateForOutMessage( refToOutMessageId: outMessage.Id, maxRetryCount: 2, retryInterval: TimeSpan.FromSeconds(1), type: RetryType.Send)); var ctx = new MessagingContext( tobeSendMessage, new ReceivedEntityMessage( outMessage, tobeSendMessage.ToStream(), tobeSendMessage.ContentType), MessagingContextMode.Send) { SendingPMode = CreateSendPModeWithPushUrl() }; var sabotageException = new WebException("Remote host not available"); IStep sut = CreateSendStepWithResponse( StubHttpClient.ThatThrows(sabotageException)); // Act StepResult result = await sut.ExecuteAsync(ctx); // Assert Assert.False(result.Succeeded); GetDataStoreContext.AssertRetryRelatedOutMessage( outMessage.Id, r => { Assert.NotNull(r); Assert.Equal(RetryStatus.Pending, r.Status); }); }
public async Task Use_ReceivingPMode_When_No_SendingPMode_Is_Available() { // Arrange var userMessage = new UserMessage($"user-{Guid.NewGuid()}"); var message = AS4Message.Create(userMessage); var output = new MemoryStream(); await SerializerProvider .Default .Get(message.ContentType) .SerializeAsync(message, output); var ctx = new MessagingContext( message, new ReceivedMessage(output, message.ContentType), MessagingContextMode.Send) { ReceivingPMode = new ReceivingProcessingMode { ReplyHandling = { ResponseConfiguration = new PushConfiguration { Protocol ={ Url = "http://some/endpoint/path" } } } } }; var receipt = new Receipt($"receipt-{Guid.NewGuid()}", userMessage.MessageId); var stub = StubHttpClient.ThatReturns(AS4Message.Create(receipt)); IStep sut = CreateSendStepWithResponse(stub); // Act StepResult result = await sut.ExecuteAsync(ctx); // Assert Assert.True(result.Succeeded, "Sending UserMessage step has not succeeded"); Assert.Equal(receipt, result.MessagingContext.AS4Message.PrimaryMessageUnit); // TearDown ctx.Dispose(); }
/// <summary> /// Emulates the processing of the request based on the named configuration. /// </summary> /// <param name="name">The name of the processor configuration.</param> /// <returns> /// An <see cref="OkObjectResult"/> if all steps successful. /// An <see cref="ObjectResult"/> with Status418ImATeapot when configured to simulate an error. /// An <see cref="ObjectResult"/> with Status500InternalServerError if an unexpected error occurs. /// </returns> public async Task <IActionResult> ProcessRequestAsync(string name) { if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentException($"{nameof(name)} cannot be null or whitespace", nameof(name)); } IRequestProcessor processor = registry.GetRequestProcessor(name); await Task.Delay(processor.IngressLatencyMilliseconds); ObjectResult errorResult = new ObjectResult(processor.ErrorPayload); foreach (string stepName in processor.Steps) { IStep step = registry.GetStep(stepName); ExecutionStatus status = ExecutionStatus.Fail; status = step.ParallelCount == null || step.ParallelCount < 2 ? await step.ExecuteAsync().ConfigureAwait(false) : await ExcuteStepInParallel(name, stepName, step).ConfigureAwait(false); switch (status) { case ExecutionStatus.Success: log.LogInformation("{Step} completed with success in {Processor}", stepName, name); continue; case ExecutionStatus.SimulatedFail: log.LogInformation("{Step} completed with simulated error in {Processor}", stepName, name); errorResult.StatusCode = StatusCodes.Status418ImATeapot; return(errorResult); case ExecutionStatus.Fail: default: log.LogError("{Step} experienced an unexpected error in {Processor}", stepName, name); errorResult.StatusCode = StatusCodes.Status500InternalServerError; return(errorResult); } } return(new OkObjectResult(processor.SuccessPayload)); }
private async Task <ExecutionStatus> ExcuteStepInParallel(string name, string stepName, IStep step) { log.LogDebug("Executing {Step} {ParallelCount} times in parallel", stepName, step.ParallelCount); List <Task <ExecutionStatus> > tasks = new List <Task <ExecutionStatus> >(); for (int count = 0; count < step.ParallelCount; count++) { tasks.Add(step.ExecuteAsync()); } await Task.WhenAll(tasks).ConfigureAwait(false); ExecutionStatus status = ExecutionStatus.Fail; switch (step.FailOnParallelFailures) { case GroupClause.All: log.LogInformation("{Step} failure set to {GroupClause} in {Processor}, returning any success or first failure", stepName, GroupClause.All, name); status = tasks.FirstOrDefault(t => t.Result == ExecutionStatus.Success)?.Result ?? tasks.First(t => t.Result != ExecutionStatus.Success).Result; break; case GroupClause.None: log.LogInformation("{Step} failure set to {GroupClause} in {Processor}, returning success", stepName, GroupClause.None, name); status = ExecutionStatus.Success; break; case GroupClause.Undefined: case GroupClause.Any: default: log.LogInformation("{Step} failure set to {GroupClause} in {Processor}, returning first failure or success", stepName, GroupClause.Any, name); status = tasks.FirstOrDefault(t => t.Result != ExecutionStatus.Success)?.Result ?? ExecutionStatus.Success; break; } return(status); }
public async Task After_Send_Updates_Request_Operation_And_Status_To_Sent_For_Exsiting_SendPMode() { // Arrange string ebmsMessageId = $"user-{Guid.NewGuid()}"; AS4Message tobeSentMsg = AS4Message.Create(new FilledUserMessage(ebmsMessageId)); var inserted = new OutMessage(ebmsMessageId: ebmsMessageId); GetDataStoreContext.InsertOutMessage(inserted); var receivedMessage = new ReceivedEntityMessage( inserted, tobeSentMsg.ToStream(), tobeSentMsg.ContentType); var ctx = new MessagingContext( tobeSentMsg, receivedMessage, MessagingContextMode.Send) { SendingPMode = CreateSendPModeWithPushUrl() }; AS4Message receiptMessage = AS4Message.Create(new Receipt($"receipt-{Guid.NewGuid()}", $"user-{Guid.NewGuid()}")); // Act IStep sut = CreateSendStepWithResponse( StubHttpClient.ThatReturns(receiptMessage)); await sut.ExecuteAsync(ctx); // Assert GetDataStoreContext.AssertOutMessage( ebmsMessageId, message => { Assert.Equal(OutStatus.Sent, message.Status.ToEnum <OutStatus>()); Assert.Equal(Operation.Sent, message.Operation); }); }
public async Task ThenExecuteMethodSucceedsWithValidUserMessageAsync() { // Arrange string id = Guid.NewGuid().ToString(); GetDataStoreContext.InsertInMessage( CreateInMessage(id, InStatus.Received, Operation.ToBeDelivered)); DeliverMessageEnvelope envelope = AnonymousDeliverEnvelope(id); IStep sut = CreateSendDeliverStepWithSender(new SpySender()); // Act await sut.ExecuteAsync(new MessagingContext(envelope) { ReceivingPMode = CreateDefaultReceivingPMode() }); // Assert GetDataStoreContext.AssertInMessage(id, inmessage => { Assert.NotNull(inmessage); Assert.Equal(InStatus.Delivered, inmessage.Status.ToEnum <InStatus>()); Assert.Equal(Operation.Delivered, inmessage.Operation); }); }
public async Task Updates_ToBeRetried_When_Sending_Results_In_RetryableFail <T>( NotifyRetry retry, NotifyType <T> type) where T : Entity { // Arrange IStep sut = CreateSendNotifyStepWithSender(StubSenderWithResult(retry.SendResult)); string ebmsMessageId = Guid.NewGuid().ToString(); T entity = type.Insertion(GetDataStoreContext)(ebmsMessageId, retry.CurrentRetryCount, retry.MaxRetryCount); // Act await sut.ExecuteAsync(CreateNotifyMessage <T>(ebmsMessageId, entity)); // Assert type.Assertion(GetDataStoreContext)( ebmsMessageId, e => { (int _, Operation actualOperation) = type.OperationGetter(GetDataStoreContext, e); Assert.Equal(retry.ExpectedOperation, actualOperation); }); }
public async Task Reset_InMessage_Operation_ToBeDelivered_When_CurrentRetry_LessThen_MaxRetry(DeliverRetry input) { // Arrange string id = Guid.NewGuid().ToString(); InMessage im = CreateInMessage(id, InStatus.Received, Operation.Delivering); GetDataStoreContext.InsertInMessage(im); var r = RetryReliability.CreateForInMessage( refToInMessageId: im.Id, maxRetryCount: input.MaxRetryCount, retryInterval: default(TimeSpan), type: RetryType.Notification); r.CurrentRetryCount = input.CurrentRetryCount; GetDataStoreContext.InsertRetryReliability(r); DeliverMessageEnvelope envelope = AnonymousDeliverEnvelope(id); var stub = new Mock <IDeliverSender>(); stub.Setup(s => s.SendAsync(envelope)) .ReturnsAsync(input.SendResult); IStep sut = CreateSendDeliverStepWithSender(stub.Object); // Act await sut.ExecuteAsync(new MessagingContext(envelope) { ReceivingPMode = CreateDefaultReceivingPMode() }); // Assert GetDataStoreContext.AssertInMessage(id, inMessage => { Assert.NotNull(inMessage); Assert.Equal(input.ExpectedStatus, inMessage.Status.ToEnum <InStatus>()); Assert.Equal(input.ExpectedOperation, inMessage.Operation); }); }