private static Task ExecuteAsync(FabricRequest request, ICondition condition, TimeSpan delayTime, Func <TimeSpan, TimeSpan> getNextDelayTime, CancellationToken cancellationToken)
        {
            RequestPerformer    performer           = new RequestPerformer();
            DelayStrategy       delay               = new DelayStrategy(delayTime, getNextDelayTime);
            ConditionalStrategy conditionalStrategy = new ConditionalStrategy(delay, r => r.ShouldRetry);
            CompositeStrategy   compositeStrategy   = new CompositeStrategy(performer, conditionalStrategy);

            RetryLoop loop = new RetryLoop(compositeStrategy, condition);

            return(loop.PerformAsync(request, cancellationToken));
        }
 public static Predicate <IRetryContext> ExpectedInstanceCount(FabricRequest request, int expectedInstanceCount)
 {
     return(FabricRequestProcessor.ExpectedResultCount <TestServicePartitionInfo>(request, expectedInstanceCount));
 }
        public static Predicate <IRetryContext> SuccessRetryErrorCodeProcessor(FabricRequest request)
        {
            return(delegate(IRetryContext r)
            {
                if (request.OperationResult != null)
                {
                    uint errorCode = request.OperationResult.ErrorCode;
                    if (!request.SucceedErrorCodes.Contains(errorCode))
                    {
                        if (request.RetryErrorCodes.Contains(errorCode))
                        {
                            r.ShouldRetry = true;
                            r.Succeeded = false;

                            TestabilityTrace.TraceSource.WriteInfo("FabricRequestProcessor", "{0}: Request failed with '{1}'. Retry is required.", r.ActivityId, errorCode);
                        }
                        else
                        {
                            r.ShouldRetry = false;
                            r.Succeeded = false;

                            TestabilityTrace.TraceSource.WriteWarning("FabricRequestProcessor", "{0}: Request failed with '{1}'. The error code is not in success and retry error codes.", r.ActivityId, errorCode);

                            string errorMessage = StringHelper.Format(
                                "{0} failed with {1}. The error code is not in success & retry error codes.",
                                request.ToString(),
                                errorCode);

                            Func <Exception, string, Exception> translateExceptionFunction = null;
                            if (!System.Fabric.Interop.InteropExceptionMap.NativeToManagedConversion.TryGetValue((int)request.OperationResult.ErrorCode, out translateExceptionFunction))
                            {
                                TestabilityTrace.TraceSource.WriteError(
                                    "FabricRequestProcessor",
                                    "Unknown ErrorCode {0} which cannot be mapped to any Fabric related exception",
                                    request.OperationResult.ErrorCode);

                                throw new System.Fabric.FabricException(StringResources.Error_Unknown, FabricErrorCode.Unknown);
                            }

                            // Creates an inner com exception with the native error code as well and error message.
                            // This can be improved by somehow getting the original exception thrown which was handled by the code
                            Exception exceptionToThrow = translateExceptionFunction(new COMException(errorMessage, (int)request.OperationResult.ErrorCode), errorMessage);
                            throw exceptionToThrow;
                        }
                    }
                    else
                    {
                        r.ShouldRetry = false;
                        r.Succeeded = true;

                        TestabilityTrace.TraceSource.WriteNoise("FabricRequestProcessor", "{0}: Request succeeded with '{1}'.", r.ActivityId, errorCode);
                    }
                }
                else
                {
                    r.ShouldRetry = false;
                    r.Succeeded = false;
                    throw new InvalidOperationException(StringHelper.Format("Operation result is null for '{0}'", request.ToString()));
                }

                return r.Succeeded;
            });
        }
        private static Predicate <IRetryContext> ResultCountConstraint <TList, TItem>(FabricRequest request, int expectedResultCount, Func <int, int, bool> condition) where TList : IList <TItem>
        {
            ThrowIf.OutOfRange(expectedResultCount, 0, int.MaxValue, "expectedResultCount");

            return(delegate(IRetryContext r)
            {
                Predicate <IRetryContext> errorCodeChecker = FabricRequestProcessor.SuccessRetryErrorCodeProcessor(request);

                // Only check the instance count if the request was a success AND the error code is S_OK. Some resolve requests
                // are used to check if the service has been deleted properly and will not have an S_OK success associated with them...
                if (errorCodeChecker(r) && request.OperationResult.ErrorCode == 0)
                {
                    OperationResult <TList> actualResult = (OperationResult <TList>)request.OperationResult;
                    int actualResultLength = actualResult.Result.Count();

                    if (condition(actualResultLength, expectedResultCount))
                    {
                        r.ShouldRetry = false;
                        r.Succeeded = true;

                        TestabilityTrace.TraceSource.WriteNoise("FabricRequestProcessor", "{0}: Request succeeded with expected result count: '{1}'", r.ActivityId, actualResultLength);
                    }
                    else
                    {
                        ResolveServiceRequest tempRequest = request as ResolveServiceRequest;
                        if (tempRequest != null && typeof(TItem) == typeof(TestServicePartitionInfo))
                        {
                            tempRequest.PreviousResult = actualResult.Result.First() as TestServicePartitionInfo;
                        }

                        r.ShouldRetry = true;
                        r.Succeeded = false;

                        TestabilityTrace.TraceSource.WriteInfo(
                            "FabricRequestProcessor",
                            "{0}: Request failed in result count validation. Expected result count: '{1}'. Actual result count : '{2}'",
                            r.ActivityId,
                            expectedResultCount,
                            actualResultLength);
                    }
                }

                return r.Succeeded;
            });
        }
 private static Predicate <IRetryContext> ResultCountConstraint <T>(FabricRequest request, int expectedResultCount, Func <int, int, bool> condition)
 {
     return(ResultCountConstraint <T[], T>(request, expectedResultCount, condition));
 }
 public static Predicate <IRetryContext> MinimumExpectedResultCount <T>(FabricRequest request, int expectedResultCount)
 {
     return(FabricRequestProcessor.ResultCountConstraint <T>(request, expectedResultCount, (a, b) => a >= b));
 }
        private static async Task <OperationResult <TOutput> > ExecuteAsync <TOutput>(FabricRequest request, ICondition condition, CancellationToken cancellationToken)
        {
            await ExecuteAsync(request, condition, cancellationToken);

            return((OperationResult <TOutput>)request.OperationResult);
        }
        public static Task ExecuteAsync(this FabricRequest request, TimeSpan delayBetweenRetries, TimeSpan maxTimeout, CancellationToken cancellationToken)
        {
            TimeBasedCondition condition = new TimeBasedCondition(maxTimeout);

            return(ExecuteAsync(request, condition, delayBetweenRetries, x => x, cancellationToken));
        }
 private static Task ExecuteAsync(FabricRequest request, ICondition condition, CancellationToken cancellationToken)
 {
     return(ExecuteAsync(request, condition, DelayTime, x => x, cancellationToken));
 }
        public static Task <OperationResult <TOutput> > ExecuteAsync <TOutput>(this FabricRequest request, int retryCount, CancellationToken cancellationToken)
        {
            RetryCountBasedCondition condition = new RetryCountBasedCondition(retryCount);

            return(ExecuteAsync <TOutput>(request, condition, cancellationToken));
        }
        public static Task ExecuteAsync(this FabricRequest request, int retryCount, CancellationToken cancellationToken)
        {
            RetryCountBasedCondition condition = new RetryCountBasedCondition(retryCount);

            return(ExecuteAsync(request, condition, cancellationToken));
        }
 public static Task <OperationResult <TOutput> > ExecuteAsync <TOutput>(this FabricRequest request, int retryCount)
 {
     return(request.ExecuteAsync <TOutput>(retryCount, CancellationToken.None));
 }
 public static Task ExecuteAsync(this FabricRequest request, int retryCount)
 {
     return(request.ExecuteAsync(retryCount, CancellationToken.None));
 }
        public static Task <OperationResult <TOutput> > ExecuteAsync <TOutput>(this FabricRequest request, TimeSpan maxTimeout, CancellationToken cancellationToken)
        {
            TimeBasedCondition condition = new TimeBasedCondition(maxTimeout);

            return(ExecuteAsync <TOutput>(request, condition, cancellationToken));
        }
 public static Task <OperationResult <TOutput> > ExecuteAsync <TOutput>(this FabricRequest request, TimeSpan maxTimeout)
 {
     return(request.ExecuteAsync <TOutput>(maxTimeout, CancellationToken.None));
 }
 public static Predicate <IRetryContext> ExpectedPartitionCount(FabricRequest request, int expectedResultCount)
 {
     return(FabricRequestProcessor.ResultCountConstraint <ServicePartitionList, Partition>(request, expectedResultCount, (a, b) => a >= b));
 }
 public static Predicate <IRetryContext> ExpectedResultCount <TList, TItem>(FabricRequest request, int expectedResultCount) where TList : IList <TItem>
 {
     return(FabricRequestProcessor.ResultCountConstraint <TList, TItem>(request, expectedResultCount, (a, b) => a == b));
 }
 public static Task ExecuteAsync(this FabricRequest request, TimeSpan maxTimeout)
 {
     return(request.ExecuteAsync(maxTimeout, CancellationToken.None));
 }