Example #1
0
        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)));
        }
Example #3
0
        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));
     }
 }
Example #5
0
        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);
        }
Example #6
0
        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);
        }
Example #7
0
        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);
        }
Example #9
0
        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);
            });
        }
Example #10
0
        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();
        }
Example #11
0
        /// <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));
        }
Example #12
0
        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);
        }
Example #13
0
        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);
            });
        }
Example #15
0
        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);
            });
        }