Пример #1
0
        public void MessageOlderThanRetentionDateWillBeDeleted(string specificSettings)
        {
            // Arrange: Insert a "retired" OutMessage with a referenced Reception Awareness.
            OverrideWithSpecificSettings(specificSettings);

            IConfig config = EnsureLocalConfigPointsToCreatedDatastore();
            string  outReferenceId = GenId(), outStandaloneId = GenId(),
                    inMessageId = GenId(), outExceptionId = GenId(),
                    inExceptionId = GenId();

            var        spy = new DatabaseSpy(config);
            OutMessage om  = CreateOutMessage(outReferenceId, insertionTime: DayBeforeYesterday, type: MessageType.Error);

            spy.InsertOutMessage(om);
            spy.InsertRetryReliability(RetryReliability.CreateForOutMessage(om.Id, maxRetryCount: 0, retryInterval: default(TimeSpan), type: RetryType.Send));
            spy.InsertOutMessage(CreateOutMessage(outStandaloneId, insertionTime: DayBeforeYesterday, type: MessageType.Receipt));
            spy.InsertInMessage(CreateInMessage(inMessageId, DayBeforeYesterday));
            spy.InsertOutException(CreateOutException(outExceptionId, DayBeforeYesterday));
            spy.InsertInException(CreateInException(inExceptionId, DayBeforeYesterday));

            // Act: AS4.NET Component will start the Clean Up Agent.
            ExerciseStartCleaning();

            // Assert: No OutMessage or Reception Awareness entries must be found for a given EbmsMessageId.
            Assert.Empty(spy.GetOutMessages(outReferenceId, outStandaloneId));
            Assert.Null(spy.GetRetryReliabilityFor(r => r.RefToOutMessageId == om.Id));
            Assert.Empty(spy.GetInMessages(inMessageId));
            Assert.Empty(spy.GetOutExceptions(outExceptionId));
            Assert.Empty(spy.GetInExceptions(inExceptionId));
        }
Пример #2
0
        /// <summary>
        /// Inserts the out message.
        /// </summary>
        /// <param name="createContext">The create context.</param>
        /// <param name="message">The message.</param>
        /// <param name="withReceptionAwareness"></param>
        /// <returns>The OutMessage that has been inserted</returns>
        public static OutMessage InsertOutMessage(
            this Func <DatastoreContext> createContext,
            OutMessage message,
            bool withReceptionAwareness = false)
        {
            using (DatastoreContext context = createContext())
            {
                context.OutMessages.Add(message);
                context.SaveChanges();

                if (withReceptionAwareness)
                {
                    context.Add(
                        RetryReliability.CreateForOutMessage(
                            refToOutMessageId: message.Id,
                            maxRetryCount: 0,
                            retryInterval: TimeSpan.Zero,
                            type: RetryType.Send));

                    context.SaveChanges();
                }

                return(message);
            }
        }
Пример #3
0
        private static void UpdateExceptionRetry <T>(
            SendResult resultOfOperation,
            T entityToBeRetried,
            Func <IEnumerable <RetryReliability> > getRetryEntries) where T : ExceptionEntity
        {
            // There could be more In/Out Exceptions for a single message,
            // therefore we should only look for exceptions that are not yet been Notified/DeadLettered.
            if (entityToBeRetried.Operation == Operation.Notified ||
                entityToBeRetried.Operation == Operation.DeadLettered)
            {
                return;
            }

            RetryReliability rr             = getRetryEntries().FirstOrDefault();
            string           reftoMessageId =
                entityToBeRetried.EbmsRefToMessageId == null
                ? String.Empty
                : $"[{entityToBeRetried.EbmsRefToMessageId}]";

            if (resultOfOperation == SendResult.Success)
            {
                Logger.Debug($"Update {typeof(T).Name} {reftoMessageId} with Operation=Notified");
                entityToBeRetried.Operation = Operation.Notified;

                if (rr != null)
                {
                    rr.Status = RetryStatus.Completed;
                }
            }
            else
            {
                if (rr == null)
                {
                    Logger.Debug($"{typeof(T).Name} NotifyMessage failed during the notification, exhausted retries");
                    Logger.Debug($"Update {typeof(T).Name} with {{Status=Exception, Operation=DeadLettered}}");

                    entityToBeRetried.Operation = Operation.DeadLettered;
                }
                else if (resultOfOperation == SendResult.RetryableFail)
                {
                    Logger.Debug($"{typeof(T).Name} NotifyMessage failed this time, will be retried by updating Operation=ToBeRetried");

                    entityToBeRetried.Operation = Operation.ToBeRetried;
                    rr.Status = RetryStatus.Pending;
                }
                else
                {
                    Logger.Debug($"{typeof(T).Name} NotifyMessage failed during the notification, exhausted retries");
                    Logger.Debug($"Update {typeof(T).Name} with {{Status=Exception, Operation=DeadLettered}}");

                    entityToBeRetried.Operation = Operation.DeadLettered;
                    rr.Status = RetryStatus.Completed;
                }
            }
        }
Пример #4
0
        private static void UpdateMessageEntity <T>(
            SendResult resultOfOperation,
            T entityToBeRetried,
            Func <IEnumerable <RetryReliability> > getRetryEntries,
            Action <T> onCompleted,
            Action <T> onDeadLettered) where T : MessageEntity
        {
            // Only for records that are not yet been completly Notified/DeadLettered should we botter to retry
            if (entityToBeRetried.Operation == Operation.Notified ||
                entityToBeRetried.Operation == Operation.DeadLettered)
            {
                return;
            }

            RetryReliability rr = getRetryEntries().FirstOrDefault();

            if (resultOfOperation == SendResult.Success)
            {
                onCompleted(entityToBeRetried);

                Logger.Trace("Successful result, so update RetryReliability.Status=Completed");

                if (rr != null)
                {
                    rr.Status = RetryStatus.Completed;
                }
            }
            else
            {
                if (rr == null)
                {
                    Logger.Debug("Message can't be retried because no RetryReliability is configured");
                    Logger.Debug($"Update {typeof(T).Name} with {{Status=Exception, Operation=DeadLettered}}");

                    onDeadLettered(entityToBeRetried);
                    entityToBeRetried.Operation = Operation.DeadLettered;
                }
                else if (resultOfOperation == SendResult.RetryableFail)
                {
                    Logger.Debug($"Message failed this time, set for retry by updating {typeof(T).Name}.Operation=ToBeRetried");

                    entityToBeRetried.Operation = Operation.ToBeRetried;
                    rr.Status = RetryStatus.Pending;
                }
                else
                {
                    Logger.Debug("Message failed this time due to a fatal result during sending");
                    Logger.Debug($"Update {typeof(T).Name} with Status=Exception, Operation=DeadLettered");

                    onDeadLettered(entityToBeRetried);
                    entityToBeRetried.Operation = Operation.DeadLettered;
                    rr.Status = RetryStatus.Completed;
                }
            }
        }
Пример #5
0
        /// <summary>
        /// Inserts the retry reliability information referencing a <see cref="InMessage"/>.
        /// </summary>
        /// <param name="reliability">The <see cref="RetryReliability"/> entity to insert</param>
        public void InsertRetryReliability(RetryReliability reliability)
        {
            if (reliability == null)
            {
                throw new ArgumentNullException(nameof(reliability));
            }

            reliability.InsertionTime    = DateTimeOffset.Now;
            reliability.ModificationTime = DateTimeOffset.Now;

            _datastoreContext.RetryReliability.Add(reliability);
        }
Пример #6
0
        /// <summary>
        /// Updates a single <see cref="RetryReliability"/> record for a given <paramref name="id"/>.
        /// </summary>
        /// <param name="id">The identifier to locate the <see cref="RetryReliability"/> record</param>
        /// <param name="update">The update function to change the <see cref="RetryReliability"/> record</param>
        public void UpdateRetryReliability(long id, Action <RetryReliability> update)
        {
            if (update == null)
            {
                throw new ArgumentNullException(nameof(update));
            }

            RetryReliability rr = _datastoreContext.RetryReliability.SingleOrDefault(r => r.Id == id);

            if (rr != null)
            {
                update(rr);
                rr.ModificationTime = DateTimeOffset.Now;
            }
        }
Пример #7
0
        private static Property TestRelialityForEnabledFlag(
            bool isEnabled,
            int retryCount,
            TimeSpan retryInterval,
            Func <ReceivingProcessingMode, RetryReliability> getReliability,
            Action <ReceivingProcessingMode> extraFixtureSetup = null)
        {
            return(Prop.ForAll(
                       Gen.Frequency(
                           Tuple.Create(2, Gen.Constant(retryInterval.ToString())),
                           Tuple.Create(1, Arb.From <string>().Generator))
                       .ToArbitrary(),
                       retryIntervalText =>
            {
                // Arrange
                ReceivingProcessingMode pmode = CreateValidPMode();
                RetryReliability r = getReliability(pmode);
                r.IsEnabled = isEnabled;
                r.RetryCount = retryCount;
                r.RetryInterval = retryIntervalText;
                extraFixtureSetup?.Invoke(pmode);

                // Act
                ValidationResult result = ReceivingProcessingModeValidator.Instance.Validate(pmode);

                // Assert
                bool correctConfigured =
                    retryCount > 0 &&
                    r.RetryInterval.AsTimeSpan() > default(TimeSpan);

                bool expected =
                    !isEnabled && !correctConfigured ||
                    !isEnabled ||
                    correctConfigured;

                return expected.Equals(result.IsValid)
                .Label(result.AppendValidationErrorsToErrorMessage(string.Empty))
                .Classify(result.IsValid, "Valid PMode")
                .Classify(!result.IsValid, "Invalid PMode")
                .Classify(correctConfigured, "Correct Reliability")
                .Classify(!correctConfigured, "Incorrect Reliability")
                .Classify(isEnabled, "Reliability is enabled")
                .Classify(!isEnabled, "Reliability is disabled");
            }));
        }
Пример #8
0
 /// <summary>
 /// Inserts the given <see cref="RetryReliability"/> into the <see cref="DatastoreContext"/>.
 /// </summary>
 /// <param name="r"></param>
 public void InsertRetryReliability(RetryReliability r) => ChangeContext(ctx => ctx.RetryReliability.Add(r));
Пример #9
0
 /// <summary>
 /// Inserts the retry reliability on a given datastore.
 /// </summary>
 /// <param name="createContext">The factory containing the datastore to insert the <see cref="RetryReliability"/> instance</param>
 /// <param name="r">The <see cref="RetryReliability"/> instance to insert</param>
 public static void InsertRetryReliability(this Func <DatastoreContext> createContext, RetryReliability r)
 {
     using (DatastoreContext context = createContext())
     {
         context.RetryReliability.Add(r);
         context.SaveChanges();
     }
 }