public void Test_KeySeqnoObserver() { var configuration = new ClientConfiguration { Servers = new List<Uri> { new Uri(ConfigurationManager.AppSettings["bootstrapUrl"]) } }; var key = "Test_KeySeqnoObserver"; using (var cluster = new Cluster(configuration)) { using (var bucket = cluster.OpenBucket()) { bucket.Remove(key); } } configuration.Initialize(); var provider = new CarrierPublicationProvider( configuration, (pool) => new PooledIOService(pool), (config, endpoint) => new ConnectionPool<Connection>(config, endpoint), SaslFactory.GetFactory(), new DefaultConverter(), new DefaultTranscoder(new DefaultConverter(), new DefaultSerializer())); var configInfo = provider.GetConfig("default"); var features = new List<short>(); features.Add((short)ServerFeatures.MutationSeqno); var keyMapper = configInfo.GetKeyMapper(); var mappedNode = keyMapper.MapKey(key); var node = mappedNode.LocatePrimary(); foreach (var server in configInfo.Servers.Where(x=>x.IsDataNode)) { var hello = new Hello("couchbase-net-sdk/2.1.4", features.ToArray(), provider.Transcoder, 0, 0); var result3 = server.Send(hello); Assert.IsTrue(result3.Success); } var result = node.Send(new Add<string>(key, "", (VBucket)mappedNode, new DefaultTranscoder(new DefaultConverter(), new DefaultSerializer()), 1000)); var clusterController = new Mock<IClusterController>(); clusterController.Setup(x => x.Transcoder).Returns(new DefaultTranscoder()); var pending = new ConcurrentDictionary<uint, IOperation>(); var keyObserver = new KeySeqnoObserver("thekey", pending, configInfo, clusterController.Object, 0, 1000); var durabilityReached = keyObserver.Observe(result.Token, ReplicateTo.Zero, PersistTo.One); Assert.IsTrue(durabilityReached); }
/// <summary> /// Sends an operation to the server while observing it's durability requirements using async/await /// </summary> /// <typeparam name="T">The value for T.</typeparam> /// <param name="operation">A binary memcached operation - must be a mutation operation.</param> /// <param name="deletion">True if mutation is a deletion.</param> /// <param name="replicateTo">The durability requirement for replication.</param> /// <param name="persistTo">The durability requirement for persistence.</param> /// <returns>The <see cref="Task{IOperationResult}"/> to be awaited on with it's <see cref="Durability"/> status.</returns> /// <exception cref="ServiceNotSupportedException">The cluster does not support Data services.</exception> public override async Task <IOperationResult <T> > SendWithDurabilityAsync <T>(IOperation <T> operation, bool deletion, ReplicateTo replicateTo, PersistTo persistTo) { //Is the cluster configured for Data services? if (!ConfigInfo.IsDataCapable) { throw new ServiceNotSupportedException("The cluster does not support Data services."); } IOperationResult <T> result; try { result = await SendWithRetryAsync(operation); if (result.Success) { var config = ConfigInfo.ClientConfig.BucketConfigs[BucketName]; if (ConfigInfo.SupportsEnhancedDurability) { var seqnoObserver = new KeySeqnoObserver(ConfigInfo, ClusterController.Transcoder, config.ObserveInterval, (uint)config.ObserveTimeout); var observed = await seqnoObserver.ObserveAsync(result.Token, replicateTo, persistTo); result.Durability = observed ? Durability.Satisfied : Durability.NotSatisfied; } else { var observer = new KeyObserver(ConfigInfo, ClusterController.Transcoder, config.ObserveInterval, config.ObserveTimeout); var observed = await observer.ObserveAsync(operation.Key, result.Cas, deletion, replicateTo, persistTo); result.Durability = observed ? Durability.Satisfied : Durability.NotSatisfied; } } else { result.Durability = Durability.NotSatisfied; } } catch (ReplicaNotConfiguredException e) { result = new OperationResult <T> { Exception = e, Status = ResponseStatus.NoReplicasFound, Durability = Durability.NotSatisfied }; } catch (DocumentMutationLostException e) { result = new OperationResult <T> { Exception = e, Status = ResponseStatus.DocumentMutationLost, Durability = Durability.NotSatisfied }; } catch (Exception e) { result = new OperationResult <T> { Exception = e, Status = ResponseStatus.ClientFailure }; } return(result); }
/// <summary> /// Sends an operation to the server while observing its durability requirements using async/await /// </summary> /// <param name="operation">A binary memcached operation - must be a mutation operation.</param> /// <param name="deletion">True if mutation is a deletion.</param> /// <param name="replicateTo">The durability requirement for replication.</param> /// <param name="persistTo">The durability requirement for persistence.</param> /// <returns>The <see cref="Task{IOperationResult}"/> to be awaited on with its <see cref="Durability"/> status.</returns> /// <exception cref="ServiceNotSupportedException">The cluster does not support Data services.</exception> public override async Task <IOperationResult> SendWithDurabilityAsync(IOperation operation, bool deletion, ReplicateTo replicateTo, PersistTo persistTo) { IOperationResult result; try { //Is the cluster configured for Data services? if (!ConfigInfo.IsDataCapable) { throw new ServiceNotSupportedException( ExceptionUtil.GetMessage(ExceptionUtil.ServiceNotSupportedMsg, "Data")); } result = await SendWithRetryAsync(operation).ContinueOnAnyContext(); if (result.Success) { var config = ConfigInfo.ClientConfig.BucketConfigs[BucketName]; using (var cts = new CancellationTokenSource(config.ObserveTimeout)) { if (ConfigInfo.SupportsEnhancedDurability) { var seqnoObserver = new KeySeqnoObserver(operation.Key, Pending, ConfigInfo, ClusterController, config.ObserveInterval, (uint)config.ObserveTimeout); var observed = await seqnoObserver.ObserveAsync(result.Token, replicateTo, persistTo, cts) .ContinueOnAnyContext(); result.Durability = observed ? Durability.Satisfied : Durability.NotSatisfied; ((OperationResult)result).Success = result.Durability == Durability.Satisfied; } else { var observer = new KeyObserver(Pending, ConfigInfo, ClusterController, config.ObserveInterval, config.ObserveTimeout); var observed = await observer.ObserveAsync(operation.Key, result.Cas, deletion, replicateTo, persistTo, cts).ContinueOnAnyContext(); result.Durability = observed ? Durability.Satisfied : Durability.NotSatisfied; ((OperationResult)result).Success = result.Durability == Durability.Satisfied; } } } else { result.Durability = Durability.NotSatisfied; ((OperationResult)result).Success = result.Durability == Durability.Satisfied; } } catch (TaskCanceledException e) { result = new OperationResult { Id = operation.Key, Exception = e, Status = ResponseStatus.OperationTimeout, Durability = Durability.NotSatisfied, Success = false }; } catch (ReplicaNotConfiguredException e) { result = new OperationResult { Id = operation.Key, Exception = e, Status = ResponseStatus.NoReplicasFound, Durability = Durability.NotSatisfied, Success = false }; } catch (DocumentMutationLostException e) { result = new OperationResult { Id = operation.Key, Exception = e, Status = ResponseStatus.DocumentMutationLost, Durability = Durability.NotSatisfied, Success = false }; } catch (DocumentMutationException e) { result = new OperationResult { Id = operation.Key, Exception = e, Status = ResponseStatus.DocumentMutationDetected, Durability = Durability.NotSatisfied, Success = false }; } catch (Exception e) { result = new OperationResult { Id = operation.Key, Exception = e, Status = ResponseStatus.ClientFailure, Success = false }; } return(result); }
/// <summary> /// Sends an operation to the server while observing it's durability requirements /// </summary> /// <param name="operation">A binary memcached operation - must be a mutation operation.</param> /// <param name="deletion">True if mutation is a deletion.</param> /// <param name="replicateTo">The durability requirement for replication.</param> /// <param name="persistTo">The durability requirement for persistence.</param> /// <returns>The <see cref="IOperationResult"/> with it's <see cref="Durability"/> status.</returns> /// <exception cref="ServiceNotSupportedException">The cluster does not support Data services.</exception> public override IOperationResult SendWithDurability(IOperation operation, bool deletion, ReplicateTo replicateTo, PersistTo persistTo) { IOperationResult result; try { //Is the cluster configured for Data services? if (!ConfigInfo.IsDataCapable) { throw new ServiceNotSupportedException( ExceptionUtil.GetMessage(ExceptionUtil.ServiceNotSupportedMsg, "Data")); } result = SendWithRetry(operation); if (result.Success) { var config = ConfigInfo.ClientConfig.BucketConfigs[BucketName]; if (ConfigInfo.SupportsEnhancedDurability) { var seqnoObserver = new KeySeqnoObserver(operation.Key, Pending, ConfigInfo, ClusterController, config.ObserveInterval, (uint)config.ObserveTimeout); var observed = seqnoObserver.Observe(result.Token, replicateTo, persistTo); result.Durability = observed ? Durability.Satisfied : Durability.NotSatisfied; } else { var observer = new KeyObserver(Pending, ConfigInfo, ClusterController, config.ObserveInterval, config.ObserveTimeout); var observed = observer.Observe(operation.Key, result.Cas, deletion, replicateTo, persistTo); result.Durability = observed ? Durability.Satisfied : Durability.NotSatisfied; } } else { result.Durability = Durability.NotSatisfied; } } catch (ReplicaNotConfiguredException e) { result = new OperationResult { Id = operation.Key, Exception = e, Status = ResponseStatus.NoReplicasFound, Durability = Durability.NotSatisfied, OpCode = operation.OperationCode }; } catch (DocumentMutationLostException e) { result = new OperationResult { Id = operation.Key, Exception = e, Status = ResponseStatus.DocumentMutationLost, Durability = Durability.NotSatisfied, OpCode = operation.OperationCode }; } catch (Exception e) { result = new OperationResult { Id = operation.Key, Exception = e, Status = ResponseStatus.ClientFailure, OpCode = operation.OperationCode }; } return(result); }