Пример #1
0
        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;
            }
        }
Пример #2
0
        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));
        }
Пример #3
0
        /// <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));
        }
Пример #4
0
        /// <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));
        }
Пример #5
0
        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)));
        }