Esempio n. 1
0
 internal MemcachedBucket(IClusterController clusterManager, string bucketName, IByteConverter converter, ITypeTranscoder transcoder)
 {
     _clusterManager = clusterManager;
     _converter      = converter;
     _transcoder     = transcoder;
     Name            = bucketName;
 }
 public void SetUp()
 {
     _endPoint = UriExtensions.GetEndPoint(_address);
     CouchbaseClientSection section = (CouchbaseClientSection)ConfigurationManager.GetSection("couchbaseClients/couchbase");
     _clientConfig = new ClientConfiguration(section);
     _clusterManager = new ClusterController(_clientConfig);
 }
 /// <summary>
 /// Ctor for creating Cluster instance.
 /// </summary>
 /// <param name="configuration">The ClientCOnfiguration to use for initialization.</param>
 /// <param name="clusterManager">The ClusterManager instance use.</param>
 /// <remarks>
 /// This overload is primarly added for testing.
 /// </remarks>
 internal ClusterHelper(ClientConfiguration configuration, IClusterController clusterManager, ILoggerFactory loggerFactory)
 {
     _loggerFactory = loggerFactory;
     Log = _loggerFactory.CreateLogger<ClusterHelper>();
     _configuration = configuration;
     _clusterManager = clusterManager;
 }
Esempio n. 4
0
        public static Func <SocketAsyncState, Task> CompletedFuncForRetry <T>(
            ConcurrentDictionary <uint, IOperation> pending,
            IClusterController controller,
            TaskCompletionSource <IOperationResult <T> > tcs)
        {
            Func <SocketAsyncState, Task> func = async s =>
            {
                IOperation op;
                if (pending.TryRemove(s.Opaque, out op))
                {
                    var actual = (IOperation <T>)op;
                    try
                    {
                        if (s.Status == ResponseStatus.TransportFailure)
                        {
                            controller.CheckConfigUpdate(op.BucketName, s.EndPoint);
                        }

                        //check if an error occurred earlier
                        if (s.Exception != null)
                        {
                            actual.Exception = s.Exception;
                            actual.HandleClientError(s.Exception.Message, s.Status);
                            tcs.SetResult(actual.GetResultWithValue());
                            return;
                        }

                        var response = s.Data.ToArray();
                        await op.ReadAsync(response, 0, response.Length)
                        .ContinueOnAnyContext();

                        var result = actual.GetResultWithValue();
                        if (result.IsNmv())
                        {
                            var config = actual.GetConfig();
                            if (config != null)
                            {
                                controller.NotifyConfigPublished(config);
                            }
                        }
                        ((OperationResult)result).SetException();
                        tcs.SetResult(result);
                    }
                    catch (Exception e)
                    {
                        op.Exception = e;
                        op.HandleClientError(e.Message, ResponseStatus.ClientFailure);
                        tcs.SetResult(actual.GetResultWithValue());
                    }
                }
                else
                {
                    const string msg = "Cannot find callback object for operation: {0}";
                    tcs.TrySetException(new InvalidOperationException(string.Format(msg, s.Opaque)));
                }
            };

            return(func);
        }
        public void SetUp()
        {
            _endPoint = UriExtensions.GetEndPoint(_address);
            CouchbaseClientSection section = (CouchbaseClientSection)ConfigurationManager.GetSection("couchbaseClients/couchbase");

            _clientConfig   = new ClientConfiguration(section);
            _clusterManager = new ClusterController(_clientConfig);
        }
 /// <summary>
 /// Ctor for <see cref="KeyObserver"/>.
 /// </summary>
 /// <param name="pending">A queue for operations in-flight.</param>
 /// <param name="configInfo">The <see cref="IConfigInfo"/> object which represents the current cluster and client configuration.</param>
 /// <param name="clusterController">The <see cref="IClusterController"/> representing the cluster's state.</param>
 /// <param name="interval">The interval to poll.</param>
 /// <param name="timeout">The max time to wait for the durability requirements to be met.</param>
 public KeyObserver(ConcurrentDictionary<uint, IOperation> pending, IConfigInfo configInfo, IClusterController clusterController, int interval, int timeout)
 {
     _pending = pending;
     _configInfo = configInfo;
     _interval = interval;
     _timeout = timeout;
     _clusterController = clusterController;
 }
 /// <summary>
 /// Ctor for <see cref="KeyObserver"/>.
 /// </summary>
 /// <param name="pending">A queue for operations in-flight.</param>
 /// <param name="configInfo">The <see cref="IConfigInfo"/> object which represents the current cluster and client configuration.</param>
 /// <param name="clusterController">The <see cref="IClusterController"/> representing the cluster's state.</param>
 /// <param name="interval">The interval to poll.</param>
 /// <param name="timeout">The max time to wait for the durability requirements to be met.</param>
 public KeyObserver(ConcurrentDictionary <uint, IOperation> pending, IConfigInfo configInfo, IClusterController clusterController, int interval, int timeout)
 {
     _pending           = pending;
     _configInfo        = configInfo;
     _interval          = interval;
     _timeout           = timeout;
     _clusterController = clusterController;
 }
 internal ClusterManager(ClientConfiguration clientConfig, IClusterController clusterController, HttpClient httpClient, IDataMapper mapper, string username, string password)
 {
     _clientConfig      = clientConfig;
     _clusterController = clusterController;
     Mapper             = mapper;
     HttpClient         = httpClient;
     _password          = password;
     _username          = username;
 }
 /// <summary>
 /// Ctor for <see cref="KeyObserver"/>.
 /// </summary>
 /// <param name="pending">A queue for operations in-flight.</param>
 /// <param name="configInfo">The <see cref="IConfigInfo"/> object which represents the current cluster and client configuration.</param>
 /// <param name="clusterController">The <see cref="IClusterController"/> representing the cluster's state.</param>
 /// <param name="interval">The interval to poll.</param>
 /// <param name="timeout">The max time to wait for the durability requirements to be met.</param>
 public KeySeqnoObserver(string key, ConcurrentDictionary <uint, IOperation> pending, IConfigInfo configInfo, IClusterController clusterController, int interval, uint timeout)
 {
     _configInfo        = configInfo;
     _interval          = interval;
     _timeout           = timeout;
     _clusterController = clusterController;
     _pending           = pending;
     _key = key;
 }
 /// <summary>
 /// Ctor for <see cref="KeyObserver"/>.
 /// </summary>
 /// <param name="pending">A queue for operations in-flight.</param>
 /// <param name="configInfo">The <see cref="IConfigInfo"/> object which represents the current cluster and client configuration.</param>
 /// <param name="clusterController">The <see cref="IClusterController"/> representing the cluster's state.</param>
 /// <param name="interval">The interval to poll.</param>
 /// <param name="timeout">The max time to wait for the durability requirements to be met.</param>
 public KeySeqnoObserver(string key, ConcurrentDictionary<uint, IOperation> pending, IConfigInfo configInfo, IClusterController clusterController, int interval, uint timeout)
 {
     _configInfo = configInfo;
     _interval = interval;
     _timeout = timeout;
     _clusterController = clusterController;
     _pending = pending;
     _key = key;
 }
Esempio n. 11
0
        /// <summary>
        /// Ctor for creating Cluster instance with a custom <see cref="ClientConfiguration"/> configuration.
        /// </summary>
        /// <param name="configuration">The ClientCOnfiguration to use for initialization.</param>
        public Cluster(ClientConfiguration configuration)
        {
            // can't use ": this(" to call the other constructor because we need to pass "this" to the ClusterController constructor
            // so we have a bit of code duplication here

            _configuration = configuration;
            _clusterController = new ClusterController(this, configuration);
            LogConfigurationAndVersion(_configuration);
        }
 protected RequestExecuterBase(IClusterController clusterController, IConfigInfo configInfo, string bucketName, ConcurrentDictionary <uint, IOperation> pending)
 {
     ClusterController     = clusterController;
     BucketName            = bucketName;
     OperationLifeSpan     = (int)ClusterController.Configuration.DefaultOperationLifespan;
     Pending               = pending;
     VBucketRetrySleepTime = (int)configInfo.ClientConfig.VBucketRetrySleepTime;
     ConfigInfo            = configInfo;
 }
Esempio n. 13
0
        /// <summary>
        /// Ctor for creating Cluster instance with a custom <see cref="ClientConfiguration"/> configuration.
        /// </summary>
        /// <param name="configuration">The ClientCOnfiguration to use for initialization.</param>
        public Cluster(ClientConfiguration configuration)
        {
            // can't use ": this(" to call the other constructor because we need to pass "this" to the ClusterController constructor
            // so we have a bit of code duplication here

            _configuration     = configuration;
            _clusterController = new ClusterController(this, configuration);
            LogConfigurationAndVersion(_configuration);
        }
Esempio n. 14
0
 protected RequestExecuterBase(IClusterController clusterController, IConfigInfo configInfo, string bucketName, ConcurrentDictionary <uint, IOperation> pending)
 {
     ClusterController = clusterController;
     TimingEnabled     = ClusterController.Configuration.EnableOperationTiming;
     BucketName        = bucketName;
     OperationLifeSpan = (int)ClusterController.Configuration.DefaultOperationLifespan;
     Pending           = pending;
     Timer             = ClusterController.Configuration.Timer;
     ConfigInfo        = configInfo;
 }
Esempio n. 15
0
 /// <summary>
 /// Ctor for creating Cluster instance with a custom <see cref="ClientConfiguration"/> configuration.
 /// </summary>
 /// <param name="configuration">The ClientCOnfiguration to use for initialization.</param>
 public Cluster(ClientConfiguration configuration, ILoggerFactory loggerFactory)
 {
     // can't use ": this(" to call the other constructor because we need to pass "this" to the ClusterController constructor
     // so we have a bit of code duplication here
     _loggerFactory = loggerFactory;
     Log = _loggerFactory.CreateLogger<Cluster>();
     _configuration = configuration;
     _clusterController = new ClusterController(this, configuration, _loggerFactory);
     LogConfigurationAndVersion(_configuration);
 }
        /// <summary>
        /// Initializes a new Cluster instance with a given ClientConfiguration and ClusterManager.
        /// This overload is primarily provided for testing given that it allows you to set the
        /// major dependencies of the Cluster class and it's scope is internal.
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="clusterManager"></param>
        internal static void Initialize(ClientConfiguration configuration, IClusterController clusterManager)
        {
            if (configuration == null || clusterManager == null)
            {
                throw new ArgumentNullException(configuration == null ? "configuration" : "clusterManager");
            }

            configuration.Initialize();
            var factory = new Func <Cluster>(() => new Cluster(configuration, clusterManager));

            Initialize(factory);
        }
Esempio n. 17
0
 public MemcachedRequestExecuter(IClusterController clusterController, IConfigInfo configInfo,
                                 string bucketName, ConcurrentDictionary <uint, IOperation> pending)
     : base(clusterController, configInfo, bucketName, pending)
 {
 }
        public static Func <SocketAsyncState, Task> CompletedFuncWithRetryForCouchbase(IRequestExecuter executer,
                                                                                       ConcurrentDictionary <uint, IOperation> pending, IClusterController controller,
                                                                                       TaskCompletionSource <IOperationResult> tcs, CancellationToken cancellationToken)
        {
            Func <SocketAsyncState, Task> func = async s =>
            {
                IOperation op;
                if (pending.TryRemove(s.Opaque, out op))
                {
                    try
                    {
                        //check if an error occurred earlier
                        if (s.Exception != null)
                        {
                            op.Exception = s.Exception;
                            op.HandleClientError(s.Exception.Message, s.Status);
                            tcs.SetResult(op.GetResult());
                            return;
                        }

                        var response = s.Data.ToArray();
                        await op.ReadAsync(response, 0, response.Length)
                        .ContinueOnAnyContext();

                        var result = op.GetResult();
                        if (result.Success)
                        {
                            tcs.SetResult(result);
                        }
                        else
                        {
                            if (result.IsNmv())
                            {
                                var config = op.GetConfig();
                                if (config != null)
                                {
                                    controller.NotifyConfigPublished(config);
                                }
                            }
                            if (result.IsNmv() || (op.CanRetry() && result.ShouldRetry()))
                            {
                                var retryResult = await executer.RetryOperationEveryAsync((o, c) =>
                                {
                                    var retryTcs = new TaskCompletionSource <IOperationResult>();

                                    var cloned       = o.Clone();
                                    cloned.Completed = CompletedFuncForRetry(executer, pending, controller, retryTcs);
                                    pending.TryAdd(cloned.Opaque, cloned);

                                    var keyMapper = c.GetKeyMapper();
                                    var vBucket   = (IVBucket)keyMapper.MapKey(o.Key);
                                    o.VBucket     = vBucket;

                                    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(o).ContinueOnAnyContext();

                                    return(retryTcs.Task);
                                }, op, executer.ConfigInfo, cancellationToken).ContinueOnAnyContext();

                                tcs.SetResult(retryResult);
                            }
                            else
                            {
                                tcs.SetResult(result);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        op.Exception = e;
                        op.HandleClientError(e.Message, ResponseStatus.ClientFailure);
                        tcs.SetResult(op.GetResult());
                    }
                }
                else
                {
                    const string msg = "Cannot find callback object for operation: {0}";
                    tcs.SetException(new InvalidOperationException(string.Format(msg, s.Opaque)));
                }
            };

            return(func);
        }
Esempio n. 19
0
 /// <summary>
 /// Ctor for creating Cluster instance.
 /// </summary>
 /// <param name="configuration">The ClientCOnfiguration to use for initialization.</param>
 /// <param name="clusterController">The ClusterManager instance use.</param>
 /// <remarks>
 /// This overload is primarly added for testing.
 /// </remarks>
 internal Cluster(ClientConfiguration configuration, IClusterController clusterController)
 {
     _configuration = configuration;
     _clusterController = clusterController;
     LogConfigurationAndVersion(_configuration);
 }
Esempio n. 20
0
 public void SetUp()
 {
     _endPoint       = UriExtensions.GetEndPoint(Address);
     _clientConfig   = new ClientConfiguration();
     _clusterManager = new ClusterController(_clientConfig);
 }
 /// <summary>
 /// Ctor for creating Cluster instance.
 /// </summary>
 /// <param name="configuration">The ClientCOnfiguration to use for initialization.</param>
 /// <param name="clusterManager">The ClusterManager instance use.</param>
 /// <remarks>
 /// This overload is primarly added for testing.
 /// </remarks>
 internal ClusterHelper(ClientConfiguration configuration, IClusterController clusterManager)
 {
     _configuration  = configuration;
     _clusterManager = clusterManager;
 }
Esempio n. 22
0
        public static Func <SocketAsyncState, Task> CompletedFuncForRetry(IRequestExecuter executer,
                                                                          ConcurrentDictionary <uint, IOperation> pending, IClusterController controller,
                                                                          TaskCompletionSource <IOperationResult> tcs)
        {
            Func <SocketAsyncState, Task> func = async s =>
            {
                IOperation op;
                if (pending.TryRemove(s.Opaque, out op))
                {
                    try
                    {
                        var response = s.Data.ToArray();
                        await op.ReadAsync(response, 0, response.Length)
                        .ContinueOnAnyContext();

                        var result = op.GetResult();
                        if (result.IsNmv())
                        {
                            var config = op.GetConfig();
                            if (config != null)
                            {
                                controller.NotifyConfigPublished(config);
                            }
                        }
                        tcs.SetResult(result);
                    }
                    catch (Exception e)
                    {
                        op.Exception = e;
                        op.HandleClientError(e.Message, ResponseStatus.ClientFailure);
                        tcs.SetResult(op.GetResult());
                    }
                }
                else
                {
                    const string msg = "Cannot find callback object for operation: {0}";
                    tcs.SetException(new InvalidOperationException(string.Format(msg, s.Opaque)));
                }
            };

            return(func);
        }
Esempio n. 23
0
 public ConfigMonitor([NotNull] IClusterController clusterController, CancellationTokenSource cts)
 {
     _cts = cts;
     ClusterController = clusterController;
     Configuration     = ClusterController.Configuration;
 }
Esempio n. 24
0
 public ConfigMonitor([NotNull] IClusterController clusterController)
     : this(clusterController, new CancellationTokenSource())
 {
 }
Esempio n. 25
0
        public static Func <SocketAsyncState, Task> CompletedFuncWithRetryForCouchbase(IRequestExecuter executer,
                                                                                       ConcurrentDictionary <uint, IOperation> pending, IClusterController controller,
                                                                                       TaskCompletionSource <IOperationResult> tcs, CancellationToken cancellationToken)
        {
            Func <SocketAsyncState, Task> func = async s =>
            {
                var header = CreateHeader(s, out var errorCode, out var serverDuration);

                IOperation op;
                if (pending.TryRemove(s.Opaque, out op))
                {
                    try
                    {
                        if (s.Status == ResponseStatus.TransportFailure)
                        {
                            controller.CheckConfigUpdate(op.BucketName, s.EndPoint);
                        }

                        //check if an error occurred earlier
                        if (s.Exception != null)
                        {
                            op.Exception = s.Exception;
                            op.HandleClientError(s.Exception.Message, s.Status);
                            tcs.SetResult(op.GetResult());
                            return;
                        }

                        var response = s.Data.ToArray();
                        await op.ReadAsync(response, header, errorCode).ContinueOnAnyContext();

                        var result = op.GetResult(controller.Configuration.Tracer, executer.ConfigInfo.BucketName);
                        if (result.Success)
                        {
                            tcs.SetResult(result);
                        }
                        else
                        {
                            if (result.IsNmv())
                            {
                                var config = op.GetConfig(controller.ServerConfigTranscoder);
                                if (config != null)
                                {
                                    controller.NotifyConfigPublished(config);
                                }
                            }
                            if (result.IsNmv() || (op.CanRetry() && result.ShouldRetry()))
                            {
                                Log.Trace("Retry {0} on {1}: {2}", op.Opaque, op.CurrentHost, result.Status);
                                var retryResult = await executer.RetryOperationEveryAsync((o, c) =>
                                {
                                    var retryTcs = new TaskCompletionSource <IOperationResult>();

                                    var cloned       = o.Clone();
                                    cloned.Completed = CompletedFuncForRetry(pending, controller, retryTcs);
                                    pending.TryAdd(cloned.Opaque, cloned);

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

                                    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(o).ContinueOnAnyContext();

                                    return(retryTcs.Task);
                                }, op, executer.ConfigInfo, cancellationToken).ContinueOnAnyContext();

                                tcs.SetResult(retryResult);
                            }
                            else
                            {
                                ((OperationResult)result).SetException();
                                tcs.SetResult(result);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        op.Exception = e;
                        op.HandleClientError(e.Message, ResponseStatus.ClientFailure);
                        tcs.SetResult(op.GetResult());
                    }
                    finally
                    {
                        s.Dispose();
                    }
                }
                else
                {
                    s.Dispose();
                    const string msg = "Cannot find callback object for operation: {0}";
                    tcs.TrySetException(new InvalidOperationException(string.Format(msg, s.Opaque)));

                    controller.Configuration.OrphanedOperationReporter.Add(s.EndPoint.ToString(), s.CorrelationId, serverDuration);
                }
            };

            return(func);
        }
        /// <summary>
        /// Initializes a new Cluster instance with a given ClientConfiguration and ClusterManager.
        /// This overload is primarily provided for testing given that it allows you to set the
        /// major dependencies of the Cluster class and it's scope is internal.
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="clusterManager"></param>
        internal static void Initialize(ClientConfiguration configuration, IClusterController clusterManager)
        {
            if (configuration == null || clusterManager == null)
            {
                throw new ArgumentNullException(configuration == null ? "configuration" : "clusterManager");
            }

            configuration.Initialize();
            var factory = new Func<Cluster>(() => new Cluster(configuration, clusterManager));
            Initialize(factory);
        }
Esempio n. 27
0
        public static Func <SocketAsyncState, Task> CompletedFuncForRetry(
            ConcurrentDictionary <uint, IOperation> pending,
            IClusterController controller,
            TaskCompletionSource <IOperationResult> tcs)
        {
            Func <SocketAsyncState, Task> func = async s =>
            {
                var header = CreateHeader(s, out var errorCode, out var serverDuration);

                IOperation op;
                if (pending.TryRemove(s.Opaque, out op))
                {
                    try
                    {
                        if (s.Status == ResponseStatus.TransportFailure)
                        {
                            controller.CheckConfigUpdate(op.BucketName, s.EndPoint);
                        }

                        //check if an error occurred earlier
                        if (s.Exception != null)
                        {
                            op.Exception = s.Exception;
                            op.HandleClientError(s.Exception.Message, s.Status);
                            tcs.SetResult(op.GetResult());
                            return;
                        }

                        var response = s.Data.ToArray();
                        await op.ReadAsync(response, header, errorCode).ContinueOnAnyContext();

                        var result = op.GetResult(controller.Configuration.Tracer, null);
                        if (result.IsNmv())
                        {
                            var config = op.GetConfig(controller.ServerConfigTranscoder);
                            if (config != null)
                            {
                                controller.NotifyConfigPublished(config);
                            }
                        }
                        ((OperationResult)result).SetException();
                        tcs.SetResult(result);
                    }
                    catch (Exception e)
                    {
                        op.Exception = e;
                        op.HandleClientError(e.Message, ResponseStatus.ClientFailure);
                        tcs.SetResult(op.GetResult());
                    }
                    finally
                    {
                        s.Dispose();
                    }
                }
                else
                {
                    s.Dispose();
                    const string msg = "Cannot find callback object for operation: {0}";
                    tcs.TrySetException(new InvalidOperationException(string.Format(msg, s.Opaque)));

                    controller.Configuration.OrphanedOperationReporter.Add(s.EndPoint.ToString(), s.CorrelationId, serverDuration);
                }
            };

            return(func);
        }
 /// <summary>
 /// Ctor for creating Cluster instance.
 /// </summary>
 /// <param name="configuration">The ClientCOnfiguration to use for initialization.</param>
 /// <param name="clusterManager">The ClusterManager instance use.</param>
 /// <remarks>
 /// This overload is primarly added for testing.
 /// </remarks>
 internal ClusterHelper(ClientConfiguration configuration, IClusterController clusterManager)
 {
     _configuration = configuration;
     _clusterManager = clusterManager;
 }
Esempio n. 29
0
 /// <summary>
 /// Ctor for creating Cluster instance.
 /// </summary>
 /// <param name="configuration">The ClientCOnfiguration to use for initialization.</param>
 /// <param name="clusterController">The ClusterManager instance use.</param>
 /// <remarks>
 /// This overload is primarly added for testing.
 /// </remarks>
 internal Cluster(ClientConfiguration configuration, IClusterController clusterController)
 {
     _configuration     = configuration;
     _clusterController = clusterController;
     LogConfigurationAndVersion(_configuration);
 }
Esempio n. 30
0
        public static Func <SocketAsyncState, Task> CompletedFuncWithRetryForMemcached(IRequestExecuter executer,
                                                                                       ConcurrentDictionary <uint, IOperation> pending, IClusterController controller,
                                                                                       TaskCompletionSource <IOperationResult> tcs, CancellationToken cancellationToken)
        {
            Func <SocketAsyncState, Task> func = async s =>
            {
                IOperation op;
                if (pending.TryRemove(s.Opaque, out op))
                {
                    try
                    {
                        var response = s.Data.ToArray();
                        await op.ReadAsync(response, 0, response.Length)
                        .ContinueOnAnyContext();

                        var result = op.GetResult();
                        if (result.Success)
                        {
                            tcs.SetResult(result);
                        }
                        else
                        {
                            if (result.IsNmv())
                            {
                                var config = op.GetConfig();
                                if (config != null)
                                {
                                    controller.NotifyConfigPublished(config);
                                }
                            }
                            if (result.IsNmv() || (op.CanRetry() && result.ShouldRetry()))
                            {
                                var retryResult = await executer.RetryOperationEveryAsync((o, c) =>
                                {
                                    var retryTcs = new TaskCompletionSource <IOperationResult>();

                                    var cloned       = o.Clone();
                                    cloned.Completed = CompletedFuncForRetry(executer, pending, controller, retryTcs);
                                    pending.TryAdd(cloned.Opaque, cloned);

                                    var keyMapper  = c.GetKeyMapper();
                                    var mappedNode = keyMapper.MapKey(cloned.Key);
                                    var server     = mappedNode.LocatePrimary();
                                    server.SendAsync(o).ContinueOnAnyContext();

                                    return(retryTcs.Task);
                                }, op, executer.ConfigInfo, cancellationToken).ContinueOnAnyContext();

                                tcs.SetResult(retryResult);
                            }
                            else
                            {
                                tcs.SetResult(result);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        op.Exception = e;
                        op.HandleClientError(e.Message, ResponseStatus.ClientFailure);
                        tcs.SetResult(op.GetResult());
                    }
                }
                else
                {
                    const string msg = "Cannot find callback object for operation: {0}";
                    tcs.SetException(new InvalidOperationException(string.Format(msg, s.Opaque)));
                }
            };

            return(func);
        }