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()); }
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()); }