/// <summary>
        /// Sends a <see cref="IOperation" /> to the Couchbase Server using the Memcached protocol using async/await.
        /// </summary>
        /// <param name="operation">The <see cref="IOperation" /> to send.</param>
        /// <returns>
        /// An <see cref="Task{IOperationResult}" /> object representing the asynchronous operation.
        /// </returns>
        public override Task <IOperationResult> SendWithRetryAsync(IOperation operation)
        {
            var tcs = new TaskCompletionSource <IOperationResult>();
            var cts = new CancellationTokenSource(OperationLifeSpan);

            cts.CancelAfter(OperationLifeSpan);

            try
            {
                operation.Completed = CallbackFactory.CompletedFuncWithRetryForMemcached(
                    this, Pending, ClusterController, tcs, cts.Token);

                Pending.TryAdd(operation.Opaque, operation);

                var server = GetServer(operation.Key);
                server.SendAsync(operation).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                tcs.TrySetResult(new OperationResult
                {
                    Exception = e,
                    Status    = ResponseStatus.ClientFailure
                });
            }
            return(tcs.Task);
        }
예제 #2
0
        /// <summary>
        /// Sends a <see cref="IOperation" /> to the Couchbase Server using the Memcached protocol using async/await.
        /// </summary>
        /// <param name="operation">The <see cref="IOperation" /> to send.</param>
        /// <returns>
        /// An <see cref="Task{IOperationResult}" /> object representing the asynchronous operation.
        /// </returns>
        public async override Task <IOperationResult> SendWithRetryAsync(IOperation operation)
        {
            var tcs = new TaskCompletionSource <IOperationResult>();
            var cts = new CancellationTokenSource(OperationLifeSpan);

            cts.CancelAfter(OperationLifeSpan);

            try
            {
                var keyMapper = ConfigInfo.GetKeyMapper();
                var vBucket   = (IVBucket)keyMapper.MapKey(operation.Key);
                operation.VBucket = vBucket;

                operation.Completed = CallbackFactory.CompletedFuncWithRetryForCouchbase(
                    this, Pending, ClusterController, tcs, cts.Token);

                Pending.TryAdd(operation.Opaque, operation);

                var server = vBucket.LocatePrimary();
                server.SendAsync(operation).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                tcs.TrySetResult(new OperationResult
                {
                    Exception = e,
                    Status    = ResponseStatus.ClientFailure
                });
            }
            return(await tcs.Task);
        }
        /// <summary>
        /// Sends a <see cref="IOperation" /> to the Couchbase Server using the Memcached protocol using async/await.
        /// </summary>
        /// <param name="operation">The <see cref="IOperation" /> to send.</param>
        /// <param name="tcs">The <see cref="TaskCompletionSource{T}"/> the represents the task to await on.</param>
        /// <param name="cts">The <see cref="CancellationTokenSource"/> for cancellation.</param>
        /// <returns>
        /// An <see cref="Task{IOperationResult}" /> object representing the asynchronous operation.
        /// </returns>
        public override async Task <IOperationResult> SendWithRetryAsync(IOperation operation,
                                                                         TaskCompletionSource <IOperationResult> tcs = null,
                                                                         CancellationTokenSource cts = null)
        {
            tcs = tcs ?? new TaskCompletionSource <IOperationResult>();
            cts = cts ?? new CancellationTokenSource(OperationLifeSpan);

            try
            {
                //Is the cluster configured for Data services?
                if (!ConfigInfo.IsDataCapable)
                {
                    tcs.SetException(new ServiceNotSupportedException(
                                         ExceptionUtil.GetMessage(ExceptionUtil.ServiceNotSupportedMsg, "Data")));
                }

                var keyMapper = ConfigInfo.GetKeyMapper();
                var vBucket   = (IVBucket)keyMapper.MapKey(operation.Key, operation.LastConfigRevisionTried);
                operation.VBucket = vBucket;
                operation.LastConfigRevisionTried = vBucket.Rev;

                operation.Completed = CallbackFactory.CompletedFuncWithRetryForCouchbase(
                    this, Pending, ClusterController, tcs, cts.Token);

                Pending.TryAdd(operation.Opaque, operation);

                IServer server;
                var     attempts = 0;
                while ((server = vBucket.LocatePrimary()) == null)
                {
                    if (attempts++ > 10)
                    {
                        throw new TimeoutException("Could not acquire a server.");
                    }
                    await Task.Delay((int)Math.Pow(2, attempts)).ContinueOnAnyContext();
                }
                Log.Debug("Starting send for {0} with {1}", operation.Opaque, server.EndPoint);
                await server.SendAsync(operation).ContinueOnAnyContext();
            }
            catch (Exception e)
            {
                tcs.TrySetResult(new OperationResult
                {
                    Id        = operation.Key,
                    Exception = e,
                    Status    = ResponseStatus.ClientFailure
                });
            }
            return(await tcs.Task.ContinueOnAnyContext());
        }
예제 #4
0
 private void CollectPendingRpc(ConnectorEx oldLeader, AsyncSocket oldSocket)
 {
     if (null != oldLeader)
     {
         // 再 Rpc.UserState 里面记录发送目的的ConnectorEx,然后这里严格判断?
         // 由于一个时候只有Leader,所以直接使用Sender也足够了吧。
         var ctxSends   = Client.GetRpcContextsToSender(oldSocket);
         var ctxPending = Client.RemoveRpcContets(ctxSends.Keys);
         foreach (var rpc in ctxPending)
         {
             Pending.TryAdd(rpc, rpc);
         }
     }
 }
        /// <summary>
        /// Sends a <see cref="IOperation" /> to the Couchbase Server using the Memcached protocol using async/await.
        /// </summary>
        /// <param name="operation">The <see cref="IOperation" /> to send.</param>
        /// <param name="tcs">The <see cref="TaskCompletionSource{T}"/> the represents the task to await on.</param>
        /// <param name="cts">The <see cref="CancellationTokenSource"/> for cancellation.</param>
        /// <returns>
        /// An <see cref="Task{IOperationResult}" /> object representing the asynchronous operation.
        /// </returns>
        public override Task <IOperationResult> SendWithRetryAsync(IOperation operation,
                                                                   TaskCompletionSource <IOperationResult> tcs = null,
                                                                   CancellationTokenSource cts = null)
        {
            tcs = tcs ?? new TaskCompletionSource <IOperationResult>();
            cts = cts ?? new CancellationTokenSource(OperationLifeSpan);

            //Is the cluster configured for Data services?
            if (!ConfigInfo.IsDataCapable)
            {
                tcs.SetException(
                    new ServiceNotSupportedException("The cluster does not support Data services."));
            }

            try
            {
                var keyMapper = ConfigInfo.GetKeyMapper();
                var vBucket   = (IVBucket)keyMapper.MapKey(operation.Key);
                operation.VBucket = vBucket;

                operation.Completed = CallbackFactory.CompletedFuncWithRetryForCouchbase(
                    this, Pending, ClusterController, tcs, cts.Token);

                Pending.TryAdd(operation.Opaque, operation);

                IServer server;
                var     attempts = 0;
                while ((server = vBucket.LocatePrimary()) == null)
                {
                    if (attempts++ > 10)
                    {
                        throw new TimeoutException("Could not acquire a server.");
                    }
                    Thread.Sleep((int)Math.Pow(2, attempts));
                }
                Log.Debug(m => m("Starting send for {0} with {1}", operation.Opaque, server.EndPoint));
                server.SendAsync(operation).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                tcs.TrySetResult(new OperationResult
                {
                    Exception = e,
                    Status    = ResponseStatus.ClientFailure
                });
            }
            return(tcs.Task);
        }
예제 #6
0
        SendForWait <TArgument, TResult>(
            Rpc <TArgument, TResult> rpc,
            bool autoResend = true,
            int timeout     = -1)
            where TArgument : Bean, new()
            where TResult : Bean, new()
        {
            if (timeout < 0)
            {
                timeout = RaftConfig.AppendEntriesTimeout + 1000;
            }

            var future = new TaskCompletionSource <Rpc <TArgument, TResult> >();

            if (autoResend)
            {
                var tmp = _Leader;
                if (null != tmp &&
                    tmp.IsHandshakeDone &&
                    rpc.Send(tmp.Socket, (p) => SendForWaitHandle(future, rpc), timeout))
                {
                    return(future);
                }

                rpc.ResponseHandle = (p) => SendForWaitHandle(future, rpc);
                rpc.Timeout        = timeout;
                Pending.TryAdd(rpc, rpc);
                return(future);
            }

            // 记录不要自动发送的请求。
            NotAutoResend[rpc] = rpc;
            if (false == rpc.Send(_Leader?.Socket,
                                  (p) =>
            {
                NotAutoResend.TryRemove(p, out var _);
                return(SendForWaitHandle(future, rpc));
            },
                                  timeout))
            {
                future.TrySetException(new Exception("Send Failed."));
            }
            ;
            return(future);
        }
예제 #7
0
        /// <summary>
        /// Sends a <see cref="IOperation" /> to the Couchbase Server using the Memcached protocol using async/await.
        /// </summary>
        /// <param name="operation">The <see cref="IOperation" /> to send.</param>
        ///  /// <param name="tcs">The <see cref="TaskCompletionSource{T}"/> the represents the task to await on.</param>
        /// <param name="cts">The <see cref="CancellationTokenSource"/> for cancellation.</param>
        /// <returns>
        /// An <see cref="Task{IOperationResult}" /> object representing the asynchronous operation.
        /// </returns>
        public override async Task <IOperationResult> SendWithRetryAsync(IOperation operation,
                                                                         TaskCompletionSource <IOperationResult> tcs = null,
                                                                         CancellationTokenSource cts = null)
        {
            tcs = tcs ?? new TaskCompletionSource <IOperationResult>();
            cts = cts ?? new CancellationTokenSource(OperationLifeSpan);

            var parentSpan = Tracer.StartParentSpan(operation, ConfigInfo.BucketName);

            try
            {
                operation.Completed = CallbackFactory.CompletedFuncWithRetryForMemcached(
                    this, Pending, ClusterController, tcs, cts.Token);

                Pending.TryAdd(operation.Opaque, operation);

                IServer server;
                var     attempts = 0;
                while ((server = GetServer(operation.Key)) == null)
                {
                    if (attempts++ > 10)
                    {
                        throw new TimeoutException("Could not acquire a server.");
                    }
                    await Task.Delay((int)Math.Pow(2, attempts)).ContinueOnAnyContext();
                }
                await server.SendAsync(operation).ContinueOnAnyContext();
            }
            catch (Exception e)
            {
                tcs.TrySetResult(new OperationResult
                {
                    Id        = operation.Key,
                    Exception = e,
                    Status    = ResponseStatus.ClientFailure
                });
            }
            finally
            {
                parentSpan.Finish();
            }

            return(await tcs.Task.ContinueOnAnyContext());
        }
예제 #8
0
        /// <summary>
        /// Sends a <see cref="IOperation{T}" /> to the Couchbase Server using the Memcached protocol using async/await.
        /// </summary>
        /// <typeparam name="T">The Type of the body of the request.</typeparam>
        /// <param name="operation">The <see cref="IOperation{T}" /> to send.</param>
        /// <param name="tcs">The <see cref="TaskCompletionSource{T}"/> the represents the task to await on.</param>
        /// <param name="cts">The <see cref="CancellationTokenSource"/> for cancellation.</param>
        /// <returns>
        /// An <see cref="Task{IOperationResult}" /> object representing the asynchronous operation.
        /// </returns>
        public override Task <IOperationResult <T> > SendWithRetryAsync <T>(IOperation <T> operation,
                                                                            TaskCompletionSource <IOperationResult <T> > tcs = null,
                                                                            CancellationTokenSource cts = null)
        {
            tcs = tcs ?? new TaskCompletionSource <IOperationResult <T> >();
            cts = cts ?? new CancellationTokenSource(OperationLifeSpan);

            try
            {
                var keyMapper = ConfigInfo.GetKeyMapper();
                var vBucket   = (IVBucket)keyMapper.MapKey(operation.Key);
                operation.VBucket = vBucket;

                operation.Completed = CallbackFactory.CompletedFuncWithRetryForCouchbase(
                    this, Pending, ClusterController, tcs, cts.Token);

                Pending.TryAdd(operation.Opaque, operation);

                IServer server;
                var     attempts = 0;
                while ((server = vBucket.LocatePrimary()) == null)
                {
                    if (attempts++ > 10)
                    {
                        throw new TimeoutException("Could not acquire a server.");
                    }
                    Thread.Sleep((int)Math.Pow(2, attempts));
                }
                server.SendAsync(operation).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                tcs.TrySetResult(new OperationResult <T>
                {
                    Exception = e,
                    Status    = ResponseStatus.ClientFailure
                });
            }
            return(tcs.Task);
        }
예제 #9
0
        /// <summary>
        /// 发送Rpc请求。
        /// 如果 autoResend == true,那么总是返回成功。内部会在需要的时候重发请求。
        /// 如果 autoResend == false,那么返回结果表示是否成功。
        /// </summary>
        /// <typeparam name="TArgument"></typeparam>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="rpc"></param>
        /// <param name="handle"></param>
        /// <param name="autoResend"></param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public bool Send <TArgument, TResult>(
            Rpc <TArgument, TResult> rpc,
            Func <Protocol, int> handle,
            bool autoResend = true,
            int timeout     = -1)
            where TArgument : Bean, new()
            where TResult : Bean, new()
        {
            if (timeout < 0)
            {
                timeout = RaftConfig.AppendEntriesTimeout + 1000;
            }

            if (autoResend)
            {
                var tmp = _Leader;
                if (null != tmp &&
                    tmp.IsHandshakeDone &&
                    rpc.Send(tmp.Socket, handle, timeout))
                {
                    return(true);
                }

                rpc.ResponseHandle = handle;
                rpc.Timeout        = timeout;
                Pending.TryAdd(rpc, rpc);
                return(true);
            }

            // 记录不要自动发送的请求。
            NotAutoResend[rpc] = rpc;
            return(rpc.Send(_Leader?.Socket, (p) =>
            {
                NotAutoResend.TryRemove(p, out var _);
                return handle(p);
            },
                            timeout));
        }
예제 #10
0
        /// <summary>
        /// Sends a <see cref="IOperation" /> to the Couchbase Server using the Memcached protocol using async/await.
        /// </summary>
        /// <param name="operation">The <see cref="IOperation" /> to send.</param>
        ///  /// <param name="tcs">The <see cref="TaskCompletionSource{T}"/> the represents the task to await on.</param>
        /// <param name="cts">The <see cref="CancellationTokenSource"/> for cancellation.</param>
        /// <returns>
        /// An <see cref="Task{IOperationResult}" /> object representing the asynchronous operation.
        /// </returns>
        public override Task <IOperationResult> SendWithRetryAsync(IOperation operation,
                                                                   TaskCompletionSource <IOperationResult> tcs = null,
                                                                   CancellationTokenSource cts = null)
        {
            tcs = tcs ?? new TaskCompletionSource <IOperationResult>();
            cts = cts ?? new CancellationTokenSource(OperationLifeSpan);

            try
            {
                operation.Completed = CallbackFactory.CompletedFuncWithRetryForMemcached(
                    this, Pending, ClusterController, tcs, cts.Token);

                Pending.TryAdd(operation.Opaque, operation);

                IServer server;
                var     attempts = 0;
                while ((server = GetServer(operation.Key)) == null)
                {
                    if (attempts++ > 10)
                    {
                        throw new TimeoutException("Could not acquire a server.");
                    }
                    Thread.Sleep((int)Math.Pow(2, attempts));
                }
                server.SendAsync(operation).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                tcs.TrySetResult(new OperationResult
                {
                    Id        = operation.Key,
                    Exception = e,
                    Status    = ResponseStatus.ClientFailure
                });
            }
            return(tcs.Task);
        }