/// <summary> /// Handles the execution exception. /// </summary> /// <param name="exception">The exception.</param> /// <param name="context">The context.</param> /// <returns></returns> public async Task <MessagingContext> HandleExecutionException(Exception exception, MessagingContext context) { Logger.Error(exception.Message); using (DatastoreContext db = _createContext()) { await db.TransactionalAsync(async ctx => { var repository = new DatastoreRepository(ctx); var service = new ExceptionService(_configuration, repository, _bodyStore); InException entity = context.SubmitMessage != null ? await service.InsertIncomingSubmitExceptionAsync(exception, context.SubmitMessage, context.ReceivingPMode) : await service.InsertIncomingAS4MessageExceptionAsync(exception, context.EbmsMessageId, context.ReceivingPMode); await ctx.SaveChangesAsync(); service.InsertRelatedRetryReliability(entity, context.ReceivingPMode?.ExceptionHandling?.Reliability); await ctx.SaveChangesAsync(); }); } return(new MessagingContext(exception) { ErrorResult = context.ErrorResult }); }
public async Task ExceptionOperationIsCorrectlyPersisted() { long savedId; using (var db = GetDataStoreContext()) { var inException = InException.ForEbmsMessageId("message-id", "some-error-happened"); inException.Operation = Operation.Sent; db.InExceptions.Add(inException); await db.SaveChangesAsync(); savedId = inException.Id; Assert.NotEqual(default(long), savedId); } using (var db = GetDataStoreContext()) { var inMessage = db.InExceptions.FirstOrDefault(i => i.Id == savedId); Assert.NotNull(inMessage); Assert.Equal(Operation.Sent, inMessage.Operation); } }
public async Task InExceptionPModeInformationIsCorrectlyPersisted() { long savedId; const string pmodeId = "pmode-id1"; const string pmodeContent = "<pmode></pmode>"; using (var db = GetDataStoreContext()) { var inException = InException.ForEbmsMessageId("message-id", "some-error-happened"); inException.SetPModeInformation(pmodeId, pmodeContent); db.InExceptions.Add(inException); await db.SaveChangesAsync(); savedId = inException.Id; Assert.NotEqual(default(long), savedId); } using (var db = GetDataStoreContext()) { var inException = db.InExceptions.FirstOrDefault(i => i.Id == savedId); Assert.NotNull(inException); Assert.Equal(pmodeId, inException.PModeId); Assert.Equal(pmodeContent, inException.PMode); } }
private static InException CreateInException(string ebmsMessageId, DateTimeOffset insertionTime) { InException ex = InException.ForEbmsMessageId(ebmsMessageId, exception: string.Empty); ex.InsertionTime = insertionTime; return(ex); }
/// <summary> /// Insert an <see cref="InException"/> based on an exception that occured during an incoming operation for which we do not have a valid/complete message. /// Example: transformation. /// </summary> /// <param name="exception">The exception which message will be inserted.</param> /// <param name="messageStream">The stream that represents the message which caused the exception.</param> public async Task InsertIncomingExceptionAsync(Exception exception, Stream messageStream) { string location = await _bodyStore.SaveAS4MessageStreamAsync( _config.InExceptionStoreLocation, messageStream); InException entity = InException.ForMessageBody(location, exception); _repository.InsertInException(entity); }
/// <summary> /// Insert a given <see cref="InException"/> into the Data store.</summary> /// <param name="inException"></param> public void InsertInException(InException inException) { if (inException == null) { throw new ArgumentNullException(nameof(inException)); } inException.ModificationTime = DateTimeOffset.Now; inException.InsertionTime = DateTimeOffset.Now; _datastoreContext.InExceptions.Add(inException); }
public async void ThenInExceptionIsTransformedToNotifyEnvelope() { // Arrange ReceivedEntityMessage receivedMessage = CreateReceivedExceptionMessage(InException.ForEbmsMessageId("id", "error"), Operation.ToBeNotified); var transformer = new NotifyMessageTransformer(); var result = await transformer.TransformAsync(receivedMessage); Assert.NotNull(result.NotifyMessage); Assert.Equal( ((ExceptionEntity)receivedMessage.Entity).EbmsRefToMessageId, result.NotifyMessage.MessageInfo.RefToMessageId); }
/// <summary> /// Updates a single <see cref="InException"/> for a given <paramref name="id"/>. /// </summary> /// <param name="id">The identifier to locate the <see cref="InException"/> entity</param> /// <param name="update">The update function to change the <see cref="InException"/> entity</param> public void UpdateInException(long id, Action <InException> update) { if (update == null) { throw new ArgumentNullException(nameof(update)); } InException entity = _datastoreContext.InExceptions.Single(ex => ex.Id == id); update(entity); entity.ModificationTime = DateTimeOffset.Now; }
public async void ThenTransformSucceedsWithValidInExceptionForErrorProperties() { // Arrange ReceivedEntityMessage receivedMessage = CreateReceivedExceptionMessage(InException.ForEbmsMessageId("id", "error"), Operation.ToBeNotified); var transformer = new NotifyMessageTransformer(); // Act MessagingContext messagingContext = await transformer.TransformAsync(receivedMessage); // Assert Assert.Equal(Status.Exception, messagingContext.NotifyMessage.StatusCode); Assert.Equal(((InException)receivedMessage.Entity).EbmsRefToMessageId, messagingContext.NotifyMessage.MessageInfo.RefToMessageId); }
/// <summary> /// Insert an <see cref="InException"/> based on an exception that occured during the incoming processing of an <see cref="AS4Message"/>. /// </summary> /// <param name="exception">The exception which message will be inserted.</param> /// <param name="ebmsMessageId">The primary message id of the <see cref="AS4Message"/> that caused the exception.</param> /// <param name="pmode">The PMode that was being used during the processing.</param> public async Task <InException> InsertIncomingAS4MessageExceptionAsync(Exception exception, string ebmsMessageId, ReceivingProcessingMode pmode) { InException entity = InException .ForEbmsMessageId(ebmsMessageId, exception) .SetOperationFor(pmode?.ExceptionHandling); await entity.SetPModeInformationAsync(pmode); _repository.InsertInException(entity); _repository.UpdateInMessage(ebmsMessageId, m => m.SetStatus(InStatus.Exception)); return(entity); }
private async Task <MessagingContext> HandleNotifyException(Exception exception, MessagingContext context) { Logger.Error(exception.Message); using (var dbContext = _createContext()) { var repository = new DatastoreRepository(dbContext); if (context.NotifyMessage.EntityType == typeof(InMessage) || context.NotifyMessage.EntityType == typeof(InException)) { var inException = InException.ForEbmsMessageId(context.EbmsMessageId, exception); repository.InsertInException(inException); if (context.NotifyMessage.EntityType == typeof(InMessage)) { Logger.Debug("Fatal fail in notification, set InMessage(s).Status=Exception"); repository.UpdateInMessage(context.EbmsMessageId, i => i.SetStatus(InStatus.Exception)); } } else if (context.NotifyMessage.EntityType != typeof(OutMessage) || context.NotifyMessage.EntityType == typeof(OutException)) { var outException = OutException.ForEbmsMessageId(context.EbmsMessageId, exception); repository.InsertOutException(outException); if (context.NotifyMessage.EntityType == typeof(OutMessage) && context.MessageEntityId != null) { Logger.Debug("Fatal fail in notification, set OutMessage.Status=Exception"); repository.UpdateOutMessage( context.MessageEntityId.Value, o => o.SetStatus(OutStatus.Exception)); } } if (context.MessageEntityId != null) { Logger.Debug("Abort retry operation due to fatal notification exception, set Status=Completed"); repository.UpdateRetryReliability( context.MessageEntityId.Value, r => r.Status = RetryStatus.Completed); } await dbContext.SaveChangesAsync(); } return(new MessagingContext(exception)); }
private async Task InsertReferencedInException( MessagingContext messagingContext, CancellationToken cancellation) { using (DatastoreContext context = _createContext()) { var repository = new DatastoreRepository(context); var exception = InException.ForEbmsMessageId( messagingContext.AS4Message?.FirstSignalMessage?.RefToMessageId, new Exception(messagingContext.ErrorResult.Description)); repository.InsertInException(exception); await context.SaveChangesAsync(cancellation).ConfigureAwait(false); } }
public async Task ThenInsertInExceptionSucceeds() { // Arrange var inException = InException.ForEbmsMessageId($"inex-{Guid.NewGuid()}", "error"); // Act using (DatastoreContext context = GetDataStoreContext()) { new DatastoreRepository(context).InsertInException(inException); await context.SaveChangesAsync(); } GetDataStoreContext.AssertInException(inException.EbmsRefToMessageId, Assert.NotNull); }
public async Task InException_Is_Set_To_Notified_When_Retry_Happen_Within_Allowed_MaxRetry( HttpStatusCode secondAttempt, Operation expected) { await TestComponentWithSettings( "inexception_notify_reliability_settings.xml", async (settings, as4Msh) => { // Arrange var handler = new InboundExceptionHandler( () => new DatastoreContext(as4Msh.GetConfiguration()), as4Msh.GetConfiguration(), Registry.Instance.MessageBodyStore); const string url = "http://localhost:7071/business/inexception/"; string ebmsMessageId = $"entity-{Guid.NewGuid()}"; // Act await handler.HandleExecutionException( new Exception("This is an test exception"), new MessagingContext( new ReceivedEntityMessage(new InMessage(ebmsMessageId)), MessagingContextMode.Deliver) { ReceivingPMode = NotifyExceptionReceivePMode(url) }); // Assert SimulateNotifyFailureOnFirstAttempt(url, secondAttempt); var spy = new DatabaseSpy(as4Msh.GetConfiguration()); InException notified = await PollUntilPresent( () => spy.GetInExceptions( ex => ex.Operation == expected).FirstOrDefault(), timeout: TimeSpan.FromSeconds(10)); Entities.RetryReliability referenced = await PollUntilPresent( () => spy.GetRetryReliabilityFor(r => r.RefToInExceptionId == notified.Id), timeout: TimeSpan.FromSeconds(5)); Assert.Equal(RetryStatus.Completed, referenced.Status); }); }
/// <summary> /// Insert an <see cref="InException"/> based on an exception that occurred dring the incoming Submit operation. /// </summary> /// <param name="exception">The exception which message will be inserted.</param> /// <param name="submit">The original message that caused the exception.</param> /// <param name="pmode">The PMode that was being used during the Submit operation.</param> public async Task <InException> InsertIncomingSubmitExceptionAsync( Exception exception, SubmitMessage submit, ReceivingProcessingMode pmode) { Stream stream = await AS4XmlSerializer.ToStreamAsync(submit); string location = await _bodyStore.SaveAS4MessageStreamAsync( _config.InExceptionStoreLocation, stream); InException entity = InException .ForMessageBody(messageLocation: location, exception: exception) .SetOperationFor(pmode?.ExceptionHandling); await entity.SetPModeInformationAsync(pmode); _repository.InsertInException(entity); return(entity); }
private async Task InsertInExceptionsForNowExceptionedInMessageAsync( IEnumerable <SignalMessage> signalMessages, ErrorResult occurredError, ReceivingProcessingMode receivePMode) { if (signalMessages.Any() == false) { return; } using (DatastoreContext dbContext = _createDatastoreContext()) { var repository = new DatastoreRepository(dbContext); foreach (SignalMessage signal in signalMessages.Where(s => !(s is PullRequest))) { var ex = InException.ForEbmsMessageId(signal.MessageId, occurredError.Description); await ex.SetPModeInformationAsync(receivePMode); Logger.Debug( $"Insert InException for {signal.GetType().Name} {signal.MessageId} with {{Exception={occurredError.Description}}}"); repository.InsertInException(ex); } IEnumerable <string> ebmsMessageIds = signalMessages.Select(s => s.MessageId).ToArray(); repository.UpdateInMessages( m => ebmsMessageIds.Contains(m.EbmsMessageId), m => { Logger.Debug($"Update {m.EbmsMessageType} InMessage {m.EbmsMessageId} Status=Exception"); m.SetStatus(InStatus.Exception); }); await dbContext.SaveChangesAsync(); } }
/// <summary> /// Insert a <see cref="RetryReliability"/> record for an stored <see cref="InException"/> record. /// </summary> /// <param name="referenced">The referenced exception record.</param> /// <param name="reliability">Reliability to populate the record with retry information.</param> public void InsertRelatedRetryReliability(InException referenced, RetryReliability reliability) { if (referenced == null) { throw new ArgumentNullException(nameof(referenced)); } if (referenced.Id <= 0) { throw new InvalidOperationException( "Requires to have a stored InException to insert a referenced RetryReliability record"); } if (reliability != null && reliability.IsEnabled) { var r = Entities.RetryReliability.CreateForInException( refToInExceptionId: referenced.Id, maxRetryCount: reliability.RetryCount, retryInterval: reliability.RetryInterval.AsTimeSpan(), type: RetryType.Notification); _repository.InsertRetryReliability(r); } }
/// <summary> /// Inserts the given <see cref="InException"/> into the <see cref="DatastoreContext"/>. /// </summary> /// <param name="ex">The message.</param> public void InsertInException(InException ex) => ChangeContext(ctx => ctx.InExceptions.Add(ex));
protected virtual void SetupDataStore() { using (datastoreContext = new DatastoreContext(options, StubConfig.Default)) { string pmodeString = AS4XmlSerializer.ToString(pmode); string pmodeId = pmode.Id; { var message = new InMessage(ebmsMessageId: InEbmsMessageId1) { EbmsRefToMessageId = InEbmsRefToMessageId1, InsertionTime = DateTime.UtcNow.AddMinutes(-1), }; message.SetStatus(InStatus.Created); message.SetPModeInformation(pmodeId, pmodeString); datastoreContext.InMessages.Add(message); } { var message = new InMessage(ebmsMessageId: InEbmsMessageId2) { EbmsRefToMessageId = InEbmsRefToMessageId2, InsertionTime = DateTime.UtcNow.AddMinutes(-1) }; message.SetStatus(InStatus.Received); datastoreContext.InMessages.Add(message); } { var message = new OutMessage(OutEbmsMessageId1) { EbmsRefToMessageId = OutEbmsRefToMessageId1, InsertionTime = DateTime.UtcNow.AddMinutes(-1) }; message.SetStatus(OutStatus.Created); datastoreContext.OutMessages.Add(message); } { var message = new OutMessage(OutEbmsMessageId2) { EbmsRefToMessageId = OutEbmsRefToMessageId2, InsertionTime = DateTime.UtcNow.AddMinutes(-1) }; message.SetStatus(OutStatus.Created); datastoreContext.OutMessages.Add(message); } InException inEx1 = Entities.InException.ForEbmsMessageId(InEbmsMessageId1, InException); inEx1.InsertionTime = DateTime.UtcNow.AddMinutes(-1); datastoreContext.InExceptions.Add(inEx1); InException inEx2 = Entities.InException.ForEbmsMessageId(InEbmsMessageId1, InException); inEx2.InsertionTime = DateTime.UtcNow.AddMinutes(-1); datastoreContext.InExceptions.Add(inEx2); InException inEx3 = Entities.InException.ForMessageBody(MessageLocation, InException); inEx3.InsertionTime = DateTime.UtcNow.AddMinutes(-1); datastoreContext.InExceptions.Add(inEx3); OutException outEx1 = Entities.OutException.ForEbmsMessageId(OutEbmsRefToMessageId1, InException); outEx1.InsertionTime = DateTime.UtcNow.AddMinutes(-1); datastoreContext.OutExceptions.Add(outEx1); OutException outEx2 = OutException.ForEbmsMessageId(InEbmsRefToMessageId1, Exception); outEx2.InsertionTime = DateTime.UtcNow.AddMinutes(-1); datastoreContext.OutExceptions.Add(outEx2); OutException outEx3 = OutException.ForMessageBody(MessageLocation, Exception); outEx3.InsertionTime = DateTime.UtcNow.AddMinutes(-1); datastoreContext.OutExceptions.Add(outEx3); datastoreContext.SaveChanges(); foreach (var inMessage in datastoreContext.InMessages) { inMessage.SetPModeInformation(pmodeId, pmodeString); } foreach (var outMessage in datastoreContext.OutMessages) { outMessage.SetPModeInformation(pmodeId, pmodeString); } foreach (var inException in datastoreContext.InExceptions) { inException.SetPModeInformation(pmodeId, pmodeString); } foreach (var outException in datastoreContext.OutExceptions) { outException.SetPModeInformation(pmodeId, pmodeString); } datastoreContext.SaveChanges(); } }
/// <summary> /// Inserts the in exception. /// </summary> /// <param name="createContext">The create context.</param> /// <param name="inException">The in exception.</param> public static InException InsertInException(this Func <DatastoreContext> createContext, InException inException) { using (DatastoreContext context = createContext()) { context.InExceptions.Add(inException); context.SaveChanges(); return(inException); } }