예제 #1
0
        protected virtual Task <T> AttemptOperationAndOnFailureCallExecuteWithReplication <T>(string url, ExecuteWithReplicationState <T> state, bool avoidThrowing)
        {
            Task <Task <T> > finalTask = state.Operation(url).ContinueWith(task =>
            {
                switch (task.Status)
                {
                case TaskStatus.RanToCompletion:
                    ResetFailureCount(url);
                    var tcs = new TaskCompletionSource <T>();
                    tcs.SetResult(task.Result);
                    return(tcs.Task);

                case TaskStatus.Canceled:
                    tcs = new TaskCompletionSource <T>();
                    tcs.SetCanceled();
                    return(tcs.Task);

                case TaskStatus.Faulted:
                    Debug.Assert(task.Exception != null);
                    if (IsServerDown(task.Exception) && avoidThrowing)
                    {
                        return(ExecuteWithReplicationAsync(state));
                    }

                    tcs = new TaskCompletionSource <T>();
                    tcs.SetException(task.Exception);
                    return(tcs.Task);

                default:
                    throw new InvalidOperationException("Unknown task status in AttemptOperationAndOnFailureCallExecuteWithReplication");
                }
            });

            return(finalTask.Unwrap());
        }
예제 #2
0
        protected virtual Task <T> AttemptOperationAndOnFailureCallExecuteWithReplication <T>(OperationMetadata operationMetadata, OperationMetadata primaryOperationMetadata, ExecuteWithReplicationState <T> state, bool avoidThrowing)
        {
            var tryWithPrimaryCredentials = IsFirstFailure(operationMetadata.Url) && primaryOperationMetadata != null;

            Task <Task <T> > finalTask = state.Operation(tryWithPrimaryCredentials ? new OperationMetadata(operationMetadata.Url, primaryOperationMetadata.Credentials) : operationMetadata).ContinueWith(task =>
            {
                switch (task.Status)
                {
                case TaskStatus.RanToCompletion:
                    ResetFailureCount(operationMetadata.Url);
                    var tcs = new TaskCompletionSource <T>();
                    tcs.SetResult(task.Result);
                    return(tcs.Task);

                case TaskStatus.Canceled:
                    tcs = new TaskCompletionSource <T>();
                    tcs.SetCanceled();
                    return(tcs.Task);

                case TaskStatus.Faulted:
                    Debug.Assert(task.Exception != null);

                    if (task.Exception != null)
                    {
                        var aggregateException = task.Exception;
                        var webException       = aggregateException.ExtractSingleInnerException() as WebException;

                        if (tryWithPrimaryCredentials && operationMetadata.Credentials.HasCredentials() && webException != null)
                        {
                            IncrementFailureCount(operationMetadata.Url);

                            var response = webException.Response as HttpWebResponse;
                            if (response != null && response.StatusCode == HttpStatusCode.Unauthorized)
                            {
                                return(AttemptOperationAndOnFailureCallExecuteWithReplication(operationMetadata, primaryOperationMetadata, state, avoidThrowing));
                            }
                        }
                    }

                    bool timeoutThrown;
                    if (IsServerDown(task.Exception, out timeoutThrown) && avoidThrowing)
                    {
                        state.TimeoutThrown = timeoutThrown;
                        return(ExecuteWithReplicationAsync(state));
                    }

                    tcs = new TaskCompletionSource <T>();
                    tcs.SetException(task.Exception);
                    return(tcs.Task);

                default:
                    throw new InvalidOperationException("Unknown task status in AttemptOperationAndOnFailureCallExecuteWithReplication");
                }
            });

            return(finalTask.Unwrap());
        }