public async Task OutExceptionPModeInformationIsCorrectlyPersisted() { long savedId; const string pmodeId = "pmode-id1"; const string pmodeContent = "<pmode></pmode>"; using (var db = GetDataStoreContext()) { var outException = OutException.ForEbmsMessageId("message-id", "some-error-happened"); outException.SetPModeInformation(pmodeId, pmodeContent); db.OutExceptions.Add(outException); await db.SaveChangesAsync(); savedId = outException.Id; Assert.NotEqual(default(long), savedId); } using (var db = GetDataStoreContext()) { var outException = db.OutExceptions.FirstOrDefault(i => i.Id == savedId); Assert.NotNull(outException); Assert.Equal(pmodeId, outException.PModeId); Assert.Equal(pmodeContent, outException.PMode); } }
/// <summary> /// Handles the execution exception. /// </summary> /// <param name="exception">The exception.</param> /// <param name="context">The message context.</param> /// <returns></returns> public async Task <MessagingContext> HandleExecutionException(Exception exception, MessagingContext context) { Logger.Error($"Exception occured while executing Steps: {exception.Message}"); Logger.Trace(exception.StackTrace); if (exception.InnerException != null) { Logger.Error(exception.InnerException.Message); Logger.Trace(exception.InnerException.StackTrace); } string ebmsMessageId = await GetEbmsMessageId(context); using (DatastoreContext db = _createContext()) { await db.TransactionalAsync(async ctx => { var repository = new DatastoreRepository(ctx); var service = new ExceptionService(_configuration, repository, _bodyStore); OutException entity = context.SubmitMessage != null ? await service.InsertOutgoingSubmitExceptionAsync(exception, context.SubmitMessage, context.SendingPMode) : await service.InsertOutgoingAS4MessageExceptionAsync(exception, ebmsMessageId, context.MessageEntityId, context.SendingPMode); await ctx.SaveChangesAsync(); service.InsertRelatedRetryReliability(entity, context.SendingPMode?.ExceptionHandling?.Reliability); await ctx.SaveChangesAsync(); }); } return(new MessagingContext(exception)); }
private static OutException CreateOutException(string ebmsMessageId, DateTimeOffset insertionTime) { OutException ex = OutException.ForEbmsMessageId(ebmsMessageId, exception: string.Empty); ex.InsertionTime = insertionTime; return(ex); }
/// <summary> /// Insert an <see cref="OutException"/> based on an exception that occured during an outgoing 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 InsertOutgoingExceptionAsync(Exception exception, Stream messageStream) { string location = await _bodyStore.SaveAS4MessageStreamAsync( _config.OutExceptionStoreLocation, messageStream); OutException entity = OutException.ForMessageBody(location, exception); _repository.InsertOutException(entity); }
/// <summary> /// Insert a given <see cref="OutException"/> into the Data store. /// </summary> /// <param name="outException"></param> public void InsertOutException(OutException outException) { if (outException == null) { throw new ArgumentNullException(nameof(outException)); } outException.InsertionTime = DateTimeOffset.Now; outException.ModificationTime = DateTimeOffset.Now; _datastoreContext.OutExceptions.Add(outException); }
/// <summary> /// Updates a single <see cref="OutException"/> entity for given <paramref name="id"/>. /// </summary> /// <param name="id">The identifier to locate the <see cref="OutException"/> entity</param> /// <param name="update">The update function to change the located <see cref="OutException"/> entity</param> public void UpdateOutException(long id, Action <OutException> update) { if (update == null) { throw new ArgumentNullException(nameof(update)); } OutException entity = _datastoreContext.OutExceptions.Single(ex => ex.Id == id); update(entity); entity.ModificationTime = DateTimeOffset.Now; }
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)); }
public async void ThenOutExceptionIsTransformedToNotifyEnvelope() { // Arrange ReceivedEntityMessage receivedMessage = CreateReceivedExceptionMessage(OutException.ForEbmsMessageId("id", "error"), Operation.ToBeNotified); var transformer = new NotifyMessageTransformer(); // Act MessagingContext result = await transformer.TransformAsync(receivedMessage); // Assert Assert.NotNull(result.NotifyMessage); Assert.Equal( ((ExceptionEntity)receivedMessage.Entity).EbmsRefToMessageId, result.NotifyMessage.MessageInfo.RefToMessageId); }
public async Task ThenInsertOutExceptionSucceeds() { // Arrange var outException = OutException.ForEbmsMessageId($"outex-{Guid.NewGuid()}", "error"); // Act using (DatastoreContext context = GetDataStoreContext()) { new DatastoreRepository(context).InsertOutException(outException); await context.SaveChangesAsync(); } // Assert GetDataStoreContext.AssertOutException(outException.EbmsRefToMessageId, Assert.NotNull); }
public async Task OutException_Is_Set_To_Notified_When_Retry_Happen_Within_Allowed_MaxRetry( HttpStatusCode secondAttempt, Operation expected) { await TestComponentWithSettings( "outexception_notify_reliability_settings.xml", async (settings, as4Msh) => { // Arrange var handler = new OutboundExceptionHandler( () => new DatastoreContext(as4Msh.GetConfiguration()), as4Msh.GetConfiguration(), Registry.Instance.MessageBodyStore); const string url = "http://localhost:7070/business/outexception/"; string ebmsMessageId = $"entity-{Guid.NewGuid()}"; var spy = new DatabaseSpy(as4Msh.GetConfiguration()); //var entity = new OutMessage(ebmsMessageId); //spy.InsertOutMessage(entity); // Act await handler.HandleExecutionException( new Exception("This is an test exception"), new MessagingContext(new SubmitMessage()) { SendingPMode = NotifySendingPMode(url) }); // Arrange SimulateNotifyFailureOnFirstAttempt(url, secondAttempt); OutException notified = await PollUntilPresent( () => spy.GetOutExceptions( ex => ex.Operation == expected).FirstOrDefault(), timeout: TimeSpan.FromSeconds(10)); Entities.RetryReliability referenced = await PollUntilPresent( () => spy.GetRetryReliabilityFor(r => r.RefToOutExceptionId == notified.Id), timeout: TimeSpan.FromSeconds(5)); Assert.Equal(RetryStatus.Completed, referenced.Status); }); }
/// <summary> /// Insert an <see cref="OutException"/> based on an exception that occured during the outgoing 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="entityId">The primary key of the stored record to which the mesage is refering to.</param> /// <param name="pmode">The PMode that was used during the processing of the message.</param> public async Task <OutException> InsertOutgoingAS4MessageExceptionAsync( Exception exception, string ebmsMessageId, long?entityId, SendingProcessingMode pmode) { OutException entity = OutException .ForEbmsMessageId(ebmsMessageId, exception) .SetOperationFor(pmode?.ExceptionHandling); await entity.SetPModeInformationAsync(pmode); _repository.InsertOutException(entity); if (entityId.HasValue) { _repository.UpdateOutMessage(entityId.Value, m => m.SetStatus(OutStatus.Exception)); } return(entity); }
/// <summary> /// Insert an <see cref="OutException"/> based on an exception that occured during the outgoing Submit operation. /// </summary> /// <param name="exception">The exception which message will be inserted.</param> /// <param name="submit">The message that caused the exception.</param> /// <param name="pmode">The PMode that was being used during the Submit operation.</param> public async Task <OutException> InsertOutgoingSubmitExceptionAsync( Exception exception, SubmitMessage submit, SendingProcessingMode pmode) { Stream stream = await AS4XmlSerializer.ToStreamAsync(submit); string location = await _bodyStore.SaveAS4MessageStreamAsync( _config.OutExceptionStoreLocation, stream); OutException entity = OutException .ForMessageBody(location, exception) .SetOperationFor(pmode?.ExceptionHandling); await entity.SetPModeInformationAsync(pmode); _repository.InsertOutException(entity); return(entity); }
/// <summary> /// Insert a <see cref="RetryReliability"/> record for an stored <see cref="OutException"/> 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(OutException referenced, RetryReliability reliability) { if (referenced == null) { throw new ArgumentNullException(nameof(referenced)); } if (referenced.Id <= 0) { throw new InvalidOperationException( "Requires to have a stored OutException to insert a referenced RetryReliability record"); } if (reliability != null && reliability.IsEnabled) { var r = Entities.RetryReliability.CreateForOutException( refToOutExceptionId: referenced.Id, maxRetryCount: reliability.RetryCount, retryInterval: reliability.RetryInterval.AsTimeSpan(), type: RetryType.Notification); _repository.InsertRetryReliability(r); } }
/// <summary> /// Inserts the given <see cref="OutException"/> into the <see cref="DatastoreContext"/>. /// </summary> /// <param name="ex">The message.</param> public void InsertOutException(OutException ex) => ChangeContext(ctx => ctx.OutExceptions.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 out exception. /// </summary> /// <param name="createContext">The create context.</param> /// <param name="outException">The out exception.</param> public static OutException InsertOutException(this Func <DatastoreContext> createContext, OutException outException) { using (DatastoreContext context = createContext()) { context.OutExceptions.Add(outException); context.SaveChanges(); return(outException); } }