public async Task GetSingleResultViaPbc(Func <RiakPbcSocket, Task> useFun) { if (_disposing) { throw new RiakException((uint)ResultCode.ShuttingDown, "System currently shutting down", true); } var node = _loadBalancer.SelectNode(); if (node == null) { throw new RiakException((uint)ResultCode.ClusterOffline, "Unable to access functioning Riak node", true); } try { await node.GetSingleResultViaPbc(useFun).ConfigureAwait(false); } catch (RiakException riakException) { if (riakException.NodeOffline) { DeactivateNode(node); } throw; } }
protected override TRiakResult UseConnection <TRiakResult>(Func <IRiakConnection, TRiakResult> useFun, Func <ResultCode, string, bool, TRiakResult> onError, int retryAttempts) { if (retryAttempts < 0) { return(onError(ResultCode.NoRetries, "Unable to access a connection on the cluster.", false)); } if (_disposing) { return(onError(ResultCode.ShuttingDown, "System currently shutting down", true)); } var node = _loadBalancer.SelectNode(); if (node != null) { var result = node.UseConnection(useFun); if (!result.IsSuccess) { TRiakResult nextResult = null; if (result.ResultCode == ResultCode.NoConnections) { Thread.Sleep(RetryWaitTime); nextResult = UseConnection(useFun, onError, retryAttempts - 1); } else if (result.ResultCode == ResultCode.CommunicationError) { if (result.NodeOffline) { DeactivateNode(node); } Thread.Sleep(RetryWaitTime); nextResult = UseConnection(useFun, onError, retryAttempts - 1); } // if the next result is successful then return that if (nextResult != null && nextResult.IsSuccess) { return(nextResult); } // otherwise we'll return the result that we had at this call to make sure that // the correct/initial error is shown return(onError(result.ResultCode, result.ErrorMessage, result.NodeOffline)); } return((TRiakResult)result); } return(onError(ResultCode.ClusterOffline, "Unable to access functioning Riak node", true)); }
/// <summary> /// Executes a delegate function using a <see cref="IRiakConnection"/>, and returns the results. /// Can retry up to "<paramref name="retryAttempts"/>" times for <see cref="ResultCode.NoRetries"/> and <see cref="ResultCode.ShuttingDown"/> error states. /// This method is used over <see cref="RiakEndPoint.UseConnection"/> to keep a connection open to receive streaming results. /// </summary> /// <typeparam name="TResult">The type of the result from the <paramref name="useFun"/> parameter.</typeparam> /// <param name="useFun"> /// The delegate function to execute. Takes an <see cref="IRiakConnection"/> and an <see cref="Action"/> continuation as input, and returns a /// <see cref="RiakResult{T}"/> containing an <see cref="IEnumerable{TResult}"/> as the results of the operation. /// </param> /// <param name="retryAttempts">The number of times to retry an operation.</param> /// <returns>The results of the <paramref name="useFun"/> delegate.</returns> public override RiakResult <IEnumerable <TResult> > UseDelayedConnection <TResult>(Func <IRiakConnection, Action, RiakResult <IEnumerable <TResult> > > useFun, int retryAttempts) { if (retryAttempts < 0) { return(RiakResult <IEnumerable <TResult> > .FromError(ResultCode.NoRetries, "Unable to access a connection on the cluster (no more retries).", false)); } if (disposing) { return(RiakResult <IEnumerable <TResult> > .FromError(ResultCode.ShuttingDown, "System currently shutting down", true)); } var errorMessages = new List <string>(); var node = loadBalancer.SelectNode(); if (node != null) { var result = node.UseDelayedConnection(useFun); if (!result.IsSuccess) { errorMessages.Add(result.ErrorMessage); if (result.ResultCode == ResultCode.NoConnections) { Thread.Sleep(RetryWaitTime); return(UseDelayedConnection(useFun, retryAttempts - 1)); } if (result.ResultCode == ResultCode.CommunicationError) { MaybeDeactivateNode(result.NodeOffline, node); Thread.Sleep(RetryWaitTime); return(UseDelayedConnection(useFun, retryAttempts - 1)); } } return(result); } string msg = string.Format("Unable to access functioning Riak node, error(s): {0}", string.Join(", ", errorMessages)); return(RiakResult <IEnumerable <TResult> > .FromError(ResultCode.ClusterOffline, msg, true)); }
/// <summary> /// Executes a delegate function using a <see cref="IRiakConnection"/>, and returns the results. /// Can retry up to "<paramref name="retryAttempts"/>" times for <see cref="ResultCode.NoRetries"/> and <see cref="ResultCode.ShuttingDown"/> error states. /// This method is used over <see cref="RiakEndPoint.UseConnection"/> to keep a connection open to receive streaming results. /// </summary> /// <typeparam name="TResult">The type of the result from the <paramref name="useFun"/> parameter.</typeparam> /// <param name="useFun"> /// The delegate function to execute. Takes an <see cref="IRiakConnection"/> and an <see cref="Action"/> continuation as input, and returns a /// <see cref="RiakResult{T}"/> containing an <see cref="IEnumerable{TResult}"/> as the results of the operation. /// </param> /// <param name="retryAttempts">The number of times to retry an operation.</param> /// <returns>The results of the <paramref name="useFun"/> delegate.</returns> public override RiakResult <IEnumerable <TResult> > UseDelayedConnection <TResult>(Func <IRiakConnection, Action, RiakResult <IEnumerable <TResult> > > useFun, int retryAttempts) { if (retryAttempts < 0) { return(RiakResult <IEnumerable <TResult> > .FromError(ResultCode.NoRetries, "Unable to access a connection on the cluster.", false)); } if (disposing) { return(RiakResult <IEnumerable <TResult> > .FromError(ResultCode.ShuttingDown, "System currently shutting down", true)); } var node = loadBalancer.SelectNode(); if (node != null) { var result = node.UseDelayedConnection(useFun); if (!result.IsSuccess) { if (result.ResultCode == ResultCode.NoConnections) { Thread.Sleep(RetryWaitTime); return(UseDelayedConnection(useFun, retryAttempts - 1)); } if (result.ResultCode == ResultCode.CommunicationError) { if (result.NodeOffline) { DeactivateNode(node); } Thread.Sleep(RetryWaitTime); return(UseDelayedConnection(useFun, retryAttempts - 1)); } } return(result); } return(RiakResult <IEnumerable <TResult> > .FromError(ResultCode.ClusterOffline, "Unable to access functioning Riak node", true)); }
protected override Task <TRiakResult> UseConnection <TRiakResult>(Func <IRiakConnection, Task <TRiakResult> > useFun, Func <ResultCode, string, bool, TRiakResult> onError, int retryAttempts) { if (retryAttempts < 0) { return(TaskResult(onError(ResultCode.NoRetries, "Unable to access a connection on the cluster.", false))); } if (_disposing) { return(TaskResult(onError(ResultCode.ShuttingDown, "System currently shutting down", true))); } // use connetion with recursive fallback var node = _loadBalancer.SelectNode() as RiakNode; if (node != null) { Func <IRiakConnection, Task <RiakResult> > cUseFun = ( c => useFun(c).ContinueWith((Task <TRiakResult> t) => (RiakResult)t.Result)); // make sure the correct / initial error is shown TRiakResult originalError = null; // attempt to use the connection return(node.UseConnection(cUseFun) .ContinueWith((Task <RiakResult> finishedTask) => { var result = (TRiakResult)finishedTask.Result; if (result.IsSuccess) { return TaskResult(result); } else { originalError = onError(result.ResultCode, result.ErrorMessage, result.NodeOffline); if (result.ResultCode == ResultCode.NoConnections) { return DelayTask(RetryWaitTime) .ContinueWith(delayTask => { return UseConnection(useFun, onError, retryAttempts - 1); }).Unwrap(); } else if (result.ResultCode == ResultCode.CommunicationError) { if (result.NodeOffline) { DeactivateNode(node); } return DelayTask(RetryWaitTime) .ContinueWith(delayTask => { return UseConnection(useFun, onError, retryAttempts - 1); }).Unwrap(); } } return TaskResult(onError(result.ResultCode, result.ErrorMessage, result.NodeOffline)); }).Unwrap() .ContinueWith((Task <TRiakResult> finishedTask) => { // make sure the original error is shown if (finishedTask.Result.IsSuccess) { return finishedTask.Result; } else { return originalError; } })); } // can't get node return(TaskResult(onError(ResultCode.ClusterOffline, "Unable to access functioning Riak node", true))); }