public async Task <IExistsResult> ExistsAsync(string id, ExistsOptions options = null) { options = options ?? new ExistsOptions(); using (var existsOp = new Observe { Key = id, Cid = Cid, Transcoder = _transcoder }) { try { await _bucket.SendAsync(existsOp, options.Token, options.Timeout); var value = existsOp.GetValue(); return(new ExistsResult { Exists = existsOp.Success && value.KeyState != KeyState.NotFound && value.KeyState != KeyState.LogicalDeleted, Cas = value.Cas, Expiry = TimeSpan.FromMilliseconds(existsOp.Expires) }); } catch (KeyNotFoundException) { return(new ExistsResult { Exists = false }); } } }
public void Multiple_Property_Changes_Should_Be_Grouped_Inside_Action() { var p1 = new PropertyHelper <int>(1) { Value = 1 }; var p2 = new PropertyHelper <int>(2) { Value = 1 }; var seq = new List <int>(); Observe.Autorun(() => { seq.Add(p1.Value); seq.Add(p2.Value); }); Observe.RunInAction(() => { p1.Value = 2; p2.Value = 2; }); Observe.RunInAction(() => { p1.Value = 3; p1.Value = 4; }); Assert.True(seq.SequenceEqual(new [] { 1, 1, 2, 2, 4, 2 })); }
public async Task <IExistsResult> ExistsAsync(string id, ExistsOptions?options = null) { //sanity check for deferred bootstrapping errors _bucket.ThrowIfBootStrapFailed(); options ??= new ExistsOptions(); using var existsOp = new Observe { Key = id, Cid = Cid, CName = Name, Transcoder = _transcoder }; try { await _bucket.SendAsync(existsOp, options.TokenValue, options.TimeoutValue); var value = existsOp.GetValue(); return(new ExistsResult { Exists = existsOp.Success && value.KeyState != KeyState.NotFound && value.KeyState != KeyState.LogicalDeleted, Cas = value.Cas, Expiry = TimeSpan.FromMilliseconds(existsOp.Expires) }); } catch (KeyNotFoundException) { return(new ExistsResult { Exists = false }); } }
// Construct the CarpenterActions list. public CarpenterActions() { ResourceLibrary = new ResourceLibrary(Settings.ResourceLocation, ClassJobType.Carpenter); BasicSynthesis = new BasicSynthesis(CraftActionId.crp_BasicSynthesis, ResourceLibrary.ClassSkillImages["crp_BasicSynthesis"]); StandardSynthesis = new StandardSynthesis(CraftActionId.crp_StandardSynthesis, ResourceLibrary.ClassSkillImages["crp_StandardSynthesis"]); BasicTouch = new BasicTouch(CraftActionId.crp_BasicTouch, ResourceLibrary.ClassSkillImages["crp_BasicTouch"]); StandardTouch = new StandardTouch(CraftActionId.crp_StandardTouch, ResourceLibrary.ClassSkillImages["crp_StandardTouch"]); AdvancedTouch = new AdvancedTouch(CraftActionId.crp_AdvancedTouch, ResourceLibrary.ClassSkillImages["crp_AdvancedTouch"]); PreciseTouch = new PreciseTouch(CraftActionId.crp_PreciseTouch, ResourceLibrary.ClassSkillImages["crp_PreciseTouch"]); MastersMend = new MastersMend(CraftActionId.crp_MastersMend); MastersMendII = new MastersMendII(CraftActionId.crp_MastersMendII); SteadyHand = new SteadyHand(CraftActionId.crp_SteadyHand); InnerQuiet = new InnerQuiet(CraftActionId.crp_InnerQuiet); GreatStrides = new GreatStrides(CraftActionId.crp_GreatStrides); Observe = new Observe(CraftActionId.crp_Observe); CollectableSynthesis = new CollectableSynthesis(CraftActionId.crp_CollectableSynthesis); ByregotsBrow = new ByregotsBrow(CraftActionId.crp_ByregotsBrow); InnovativeTouch = new InnovativeTouch(CraftActionId.crp_InnovativeTouch); ByregotsMiracle = new ByregotsMiracle(CraftActionId.crp_ByregotsMiracle); NymeiasWheel = new NymeiasWheel(CraftActionId.crp_NymeiasWheel); TrainedHand = new TrainedHand(CraftActionId.crp_TrainedHand); Satisfaction = new Satisfaction(CraftActionId.crp_Satisfaction); Heart = new Heart(CraftActionId.crp_Heart); WhistleWhileYouWork = new WhistleWhileYouWork(CraftActionId.crp_WhistleWhileYouWork); PHTouch = new PHTouch(CraftActionId.crp_PreciseTouch); }
public void When_Task_Should_Propagate_Condition_Exceptions() { var ob = new Observable(); var triggered = false; var exception = false; Observe.When(() => { if (ob.Value == 10) { throw new Exception("TEST"); } return(false); }) .ContinueWith(t => { if (t.IsCompletedSuccessfully) { triggered = true; } if (t.IsFaulted && t.Exception.InnerException.Message == "TEST") { exception = true; } }, TaskContinuationOptions.ExecuteSynchronously); ob.Value = 5; Assert.False(triggered); Assert.False(exception); ob.Value = 10; Assert.False(triggered); Assert.True(exception); }
public void Autorun_Should_Be_Triggered_On_Property_Set() { var p = new PropertyHelper <int>(1); var p2 = new PropertyHelper <int>(2); p.Value = 1; var sequence = new List <int>(); Observe.Autorun(() => { sequence.Add(p.Value); if (p.Value == 10) { sequence.Add(p2.Value); } }); p.Value = 2; p2.Value = 2; p.Value = 3; p2.Value = 3; p.Value = 10; p2.Value = 10; Assert.True(sequence.SequenceEqual(new[] { 1, 2, 3, 10, 3, 10, 10 })); }
public async Task <IExistsResult> ExistsAsync(string id, ExistsOptions options) { using (var existsOp = new Observe { Key = id, Cid = Cid }) { try { await ExecuteOp(existsOp, options.Token, options.Timeout); var value = existsOp.GetValue(); return(new ExistsResult { Exists = existsOp.Success && value.KeyState != KeyState.NotFound && value.KeyState != KeyState.LogicalDeleted, Cas = value.Cas, Expiration = TimeSpan.FromMilliseconds(existsOp.Expires) }); } catch (KeyNotFoundException) { return(new ExistsResult { Exists = false }); } } }
public ObservableAwaiter(Observe <T> observable) { this.result = new None <T>(); this.onCompleted = null; this.isCompleted = false; this.observable = observable; }
/// <summary> /// Asynchronously checks the replications status of a key. /// </summary> /// <param name="observeParams">The <see cref="ObserveParams"/> object.</param> /// <param name="operation">The Observe operation.</param> /// <param name="replicaIndex">The replicaIndex of the replica within the <see cref="IVBucket"/></param> /// <returns>True if the durability requirements specified by <see cref="PersistTo"/> and <see cref="ReplicateTo"/> have been satisfied.</returns> static async Task <bool> CheckReplicaAsync(ObserveParams observeParams, Observe operation, int replicaIndex) { Log.Debug(m => m("checking replica {0}", replicaIndex)); if (observeParams.IsDurabilityMet()) { return(true); } //clone the operation since we already checked the primary and we want to maintain internal state (opaque, timer, etc) operation = (Observe)operation.Clone(); var replica = observeParams.VBucket.LocateReplica(replicaIndex); var result = await Task.Run(() => replica.Send(operation)).ContinueOnAnyContext(); Log.Debug(m => m("Replica {0} - {1} [0]", replica.EndPoint, result.Value, replicaIndex)); var state = result.Value; if (state.KeyState == observeParams.Criteria.PersistState) { Interlocked.Increment(ref observeParams.ReplicatedToCount); Interlocked.Increment(ref observeParams.PersistedToCount); } else if (state.KeyState == observeParams.Criteria.ReplicateState) { Interlocked.Increment(ref observeParams.ReplicatedToCount); } return(!observeParams.HasMutated(state.Cas)); }
private void DisposeTimers() { Controller.Dispose(); Generate.Dispose(); Detect.Dispose(); Observe.Dispose(); }
static void Main(string[] args) { var o = new Foo { Prop1 = 1, Prop2 = 1 }; Console.WriteLine("Initial run"); Observe.Autorun(() => { if (o.Prop1 == 3) { Console.WriteLine($"Prop1: {o.Prop1} Prop2: {o.Prop2}"); } else { Console.WriteLine($"Prop1: {o.Prop1}"); } }); Console.WriteLine("Setting Prop1 = 2, expecting update"); o.Prop1 = 2; Console.WriteLine("Setting Prop2 = 2, it wasn't read last time, not expecting update"); o.Prop2 = 2; Console.WriteLine("Setting Prop1 = 3, expecting update"); o.Prop1 = 3; Console.WriteLine("Setting Prop2 = 3, it was read last time, expecting update"); o.Prop2 = 3; }
/// <summary> /// Asynchronously checks the replications status of a key. /// </summary> /// <param name="observeParams">The <see cref="ObserveParams"/> object.</param> /// <param name="replicaIndex">The replicaIndex of the replica within the <see cref="IVBucket"/></param> /// <returns>True if the durability requirements specified by <see cref="PersistTo"/> and <see cref="ReplicateTo"/> have been satisfied.</returns> private async Task <bool> CheckReplicaAsync(ObserveParams observeParams, int replicaIndex) { if (observeParams.IsDurabilityMet()) { return(true); } var operation = new Observe(observeParams.Key, observeParams.VBucket, _clusterController.Transcoder, (uint)_timeout); var tcs = new TaskCompletionSource <IOperationResult <ObserveState> >(); operation.Completed = CallbackFactory.CompletedFuncForRetry(_pending, _clusterController, tcs); _pending.TryAdd(operation.Opaque, operation); var replica = observeParams.VBucket.LocateReplica(replicaIndex); await replica.SendAsync(operation).ContinueOnAnyContext(); var result = await tcs.Task.ContinueOnAnyContext(); Log.Debug("Replica {0} - {1} {2} - opaque: {3} key:{4}", replica.EndPoint, result.Value.KeyState, replicaIndex, operation.Opaque, observeParams.Key); var state = result.Value; if (state.KeyState == observeParams.Criteria.PersistState) { Interlocked.Increment(ref observeParams.ReplicatedToCount); Interlocked.Increment(ref observeParams.PersistedToCount); } else if (state.KeyState == observeParams.Criteria.ReplicateState) { Interlocked.Increment(ref observeParams.ReplicatedToCount); } return(!observeParams.HasMutated(state.Cas)); }
public void MergeAll() { Observation <string> observerA = null; Observation <string> observerB = null; Observation <string> observerC = null; Observe <string> a = x => observerA = x; Observe <string> b = x => observerB = x; Observe <string> c = x => observerC = x; Observe.Merge(a, b, c).ToList()( result => { var v = result.Value; Assert.AreEqual(4, v.Count); Assert.AreEqual("A0", v[0]); Assert.AreEqual("B0", v[1]); Assert.AreEqual("A1", v[2]); Assert.AreEqual("B1", v[3]); }); observerA(new Some <string>("A0")); observerB(new Some <string>("B0")); observerA(new Some <string>("A1")); observerB(new Some <string>("B1")); observerC(new None <string>()); observerB(new Some <string>("B2")); }
public async void Test_Observe2() { const string key = "Test_Observe2"; var remove = new Delete(key, GetVBucket(), Transcoder, OperationLifespanTimeout); var set = new Set <int?>(key, 10, GetVBucket(), Transcoder, OperationLifespanTimeout); var result = IOStrategy.Execute(set); Assert.IsTrue(result.Success); var get = new Get <dynamic>(key, GetVBucket(), Transcoder, OperationLifespanTimeout); var result1 = IOStrategy.Execute(get); Assert.IsTrue(result1.Success); Assert.AreEqual(result.Cas, result1.Cas); await Task.Delay(100); var operation = new Observe(key, GetVBucket(), Transcoder, OperationLifespanTimeout); var result2 = IOStrategy.Execute(operation); Assert.AreEqual(result1.Cas, result2.Value.Cas); Assert.AreEqual(KeyState.FoundPersisted, result2.Value.KeyState); Assert.IsTrue(result2.Success); }
public IActionResult FollowHim([FromBody] Observe observe) { if (ModelState.IsValid) { _observeRepository.Add(observe); } return(new JsonResult(observe)); }
public void Test_Observe() { const string key = "Test_Observe"; var operation = new Observe(key, GetVBucket(), new AutoByteConverter()); var result = IOStrategy.Execute(operation); Console.WriteLine(result.Message); Assert.IsTrue(result.Success); }
public void Test_Observe() { const string key = "Test_Observe"; var operation = new Observe(key, GetVBucket(), Transcoder, OperationLifespanTimeout); var result = IOService.Execute(operation); Console.WriteLine(result.Message); Assert.IsTrue(result.Success); }
static void ShowObservePattern() { Observe observe = new Observe(); observe.AddObserveItem(() => new Computer().Calc(1, 2)); observe.AddObserveItem(new Keyboard().Enter); observe.AddObserveItem(new Mouse().Click); observe.ObserveAction(); }
private Observe <WebResponse> WebRequestAsync(Uri address, bool noCache) { return(Observe.Using( () => this.CreateRequest(address, noCache), r => { Debug.WriteLine("GET " + address.OriginalString); return Observe.FromAsyncPattern(r.BeginGetResponse, r.EndGetResponse)(); })); }
/// <summary> /// Checks the replicas to see if the key has met the durability constraints defined by the caller. /// </summary> /// <param name="observeParams">The observe parameters.</param> /// <param name="operation">The operation observe operation reference; will be cloned if reused.</param> /// <returns></returns> private bool CheckReplicas(ObserveParams observeParams, Observe operation) { //Get the candidate replicas, if none are defined that match the specified durability return false. var replicas = observeParams.GetReplicas(); //Check each replica to see if has met the durability constraints specified. A mutation means we failed. var notMutated = replicas.All(index => CheckReplica(observeParams, operation, index)); return(observeParams.IsDurabilityMet() && notMutated); }
public void Test_Observe() { const string key = "Test_Observe"; var operation = new Observe(key, GetVBucket(), Transcoder, OperationLifespanTimeout); var result = IOStrategy.Execute(operation); Console.WriteLine(result.Message); Assert.IsTrue(result.Success); }
public async Task AwaitPatternWithEmptySet() { var x = await Observe.Empty <int>(); Assert.AreEqual(0, x); var y = await Observe.Empty <string>(); Assert.AreEqual(null, y); }
public void ThrowSelectMany() { bool handledError = false; Observe.Throw <int>(new InvalidOperationException("Epic Fail!")) .SelectMany(t => Observe.Return(1)).Subscribe( value => Assert.Fail("No exception thrown"), ex => { handledError = true; }, () => Assert.Fail("No exception thrown")); Assert.IsTrue(handledError); }
public IOperationResult <ObserveState> Observe(Observe operation) { var keyMapper = ConfigInfo.GetKeyMapper(); var vBucket = (IVBucket)keyMapper.MapKey(operation.Key); operation.VBucket = vBucket; var server = vBucket.LocatePrimary(); return(server.Send(operation)); }
public void Can_Write_Payload_When_Key_Has_Non_Standard_Characters() { var mockVBucket = new Mock<IVBucket>(); mockVBucket.Setup(x => x.Index).Returns(0); const string key = "ääåaasdaéö"; var operation = new Observe(key, mockVBucket.Object, new DefaultTranscoder(), 0); var result = operation.Write(); Assert.IsNotNull(result); }
public void Select() { int result = 0; int completion = 0; Observe.Return(1).Select(t => t + 1).Subscribe( x => result = x, ex => { throw ex; }, () => completion++); Assert.AreEqual(2, result); Assert.AreEqual(1, completion); }
/// <summary> /// Performs an observe event on the durability requirements specified on a key. /// </summary> /// <param name="key">The key to observe.</param> /// <param name="cas">The 'Check and Set' value of the key.</param> /// <param name="deletion">True if this is a delete operation.</param> /// <param name="replicateTo">The number of replicas that the key must be replicated to to satisfy the durability constraint.</param> /// <param name="persistTo">The number of replicas that the key must be persisted to to satisfy the durability constraint.</param> /// <returns>True if the durability constraints have been met.</returns> /// <exception cref="ReplicaNotConfiguredException">Thrown if the number of replicas requested /// in the ReplicateTo parameter does not match the # of replicas configured on the server.</exception> public bool Observe(string key, ulong cas, bool deletion, ReplicateTo replicateTo, PersistTo persistTo) { var criteria = GetDurabilityCriteria(deletion); var keyMapper = _configInfo.GetKeyMapper(); var vBucket = (IVBucket)keyMapper.MapKey(key); var p = new ObserveParams { Cas = cas, Criteria = criteria, Key = key, PersistTo = persistTo, ReplicateTo = replicateTo, VBucket = vBucket }; p.CheckConfiguredReplicas(); var operation = new Observe(key, vBucket, _clusterController.Transcoder, (uint)_timeout); do { var master = p.VBucket.LocatePrimary(); var result = master.Send(operation); var state = result.Value; if (state.KeyState == p.Criteria.PersistState) { Interlocked.Increment(ref p.PersistedToCount); } if (!deletion && p.HasMutated(state.Cas)) { return(false); } //First check if durability has already been met if (p.IsDurabilityMet()) { return(true); } //If not check each replica if (CheckReplicas(p, operation)) { return(true); } //prepare for another attempt operation = (Observe)operation.Clone(); p.Reset(); } while (!operation.TimedOut()); return(false); }
public void Test_Clone() { var operation = new Observe("key", GetVBucket(), Transcoder, OperationLifespanTimeout) { Cas = 1123 }; var cloned = operation.Clone(); Assert.AreEqual(operation.CreationTime, cloned.CreationTime); Assert.AreEqual(operation.Cas, cloned.Cas); Assert.AreEqual(operation.VBucket.Index, cloned.VBucket.Index); Assert.AreEqual(operation.Key, cloned.Key); Assert.AreEqual(operation.Opaque, cloned.Opaque); }
public void Can_Write_Payload_When_Key_Has_Non_Standard_Characters() { var mockVBucket = new Mock <IVBucket>(); mockVBucket.Setup(x => x.Index).Returns(0); const string key = "ääåaasdaéö"; var operation = new Observe(key, mockVBucket.Object, new DefaultTranscoder(), 0); var result = operation.Write(); Assert.IsNotNull(result); }
public void Return() { int count = 0; int completion = 0; Observe.Return(1).Subscribe( set => count++, ex => { throw ex; }, () => completion++); Assert.AreEqual(1, count); Assert.AreEqual(1, completion); }
public void Autorun_Should_Be_Unsubcribeable() { var p = new PropertyHelper <int>(1) { Value = 1 }; var seq = new List <int>(); var d = Observe.Autorun(() => seq.Add(p.Value)); p.Value = 2; d.Dispose(); p.Value = 3; Assert.True(seq.SequenceEqual(new [] { 1, 2 })); }
public Observe <T> GetDeserializedCachedAndRefreshedAsync <T>(Uri url, string cacheFile) where T : class { Observe <T> sequence = Observe.Empty <T>(); if (this.storage.Exists(cacheFile)) { sequence = this.storage.LoadJsonAsync <T>(cacheFile); } return(sequence.Concat( from cache in this.GetStreamAsync(url, false).Select(Json <T> .Instance.DeserializeFromStream) from _ in this.storage.SaveJsonAsync(cacheFile, cache) select cache)); }
public void ThrowSelect() { Observe.Throw <int>(new InvalidOperationException("Epic Fail!")).Select(t => t)(result => { try { var v = result.Value; Assert.Fail("No exception thrown"); } catch (InvalidOperationException) { // Expected } }); }
public void Test_Observe2() { const string key = "Test_Observe2"; var remove = new Delete(key, GetVBucket(), Converter, Serializer); var set = new Set<int>(key, 10, GetVBucket(), Converter); var result = IOStrategy.Execute(set); Assert.IsTrue(result.Success); var get = new Get<dynamic>(key, GetVBucket(), Converter, Serializer); var result1 = IOStrategy.Execute(get); Assert.IsTrue(result1.Success); Assert.AreEqual(result.Cas, result1.Cas); var operation = new Observe(key, GetVBucket(), new AutoByteConverter()); var result2 = IOStrategy.Execute(operation); Assert.AreEqual(result1.Cas, result2.Value.Cas); Assert.AreEqual(KeyState.FoundPersisted, result2.Value.KeyState); Assert.IsTrue(result2.Success); }
public async Task Test_Observe2() { const string key = "Test_Observe2"; var remove = new Delete(key, GetVBucket(), Transcoder, OperationLifespanTimeout); var set = new Set<int?>(key, 10, GetVBucket(), Transcoder, OperationLifespanTimeout); var result = IOService.Execute(set); Assert.IsTrue(result.Success); var get = new Get<dynamic>(key, GetVBucket(), Transcoder, OperationLifespanTimeout); var result1 = IOService.Execute(get); Assert.IsTrue(result1.Success); Assert.AreEqual(result.Cas, result1.Cas); await Task.Delay(100); var operation = new Observe(key, GetVBucket(), Transcoder, OperationLifespanTimeout); var result2 = IOService.Execute(operation); Assert.AreEqual(result1.Cas, result2.Value.Cas); Assert.AreEqual(KeyState.FoundPersisted, result2.Value.KeyState); Assert.IsTrue(result2.Success); }
/// <summary> /// Observes a set of keys at a specified interval and timeout. /// </summary> /// <param name="observe">The func to call at the specific interval</param> /// <param name="observeParams">The parameters to pass in.</param> /// <param name="op">The <see cref="Observe"/> operation.</param> /// <param name="interval">The interval to check.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> to use to terminate the observation at the specified timeout.</param> /// <returns>True if the durability requirements specified by <see cref="PersistTo"/> and <see cref="ReplicateTo"/> have been satisfied.</returns> static async Task<bool> ObserveEvery(Func<ObserveParams, Task<bool>> observe, ObserveParams observeParams, Observe op, int interval, CancellationToken cancellationToken) { while (true) { var result = await observe(observeParams).ContinueOnAnyContext(); if (result) { return true; } var task = Task.Delay(interval, cancellationToken).ContinueOnAnyContext(); try { await task; } catch (TaskCanceledException) { return false; } //prepare for another attempt observeParams.Reset(); op = (Observe)op.Clone(); } }
/// <summary> /// Performs an observe event on the durability requirements specified on a key. /// </summary> /// <param name="key">The key to observe.</param> /// <param name="cas">The 'Check and Set' value of the key.</param> /// <param name="deletion">True if this is a delete operation.</param> /// <param name="replicateTo">The number of replicas that the key must be replicated to to satisfy the durability constraint.</param> /// <param name="persistTo">The number of replicas that the key must be persisted to to satisfy the durability constraint.</param> /// <returns>True if the durability constraints have been met.</returns> /// <exception cref="ReplicaNotConfiguredException">Thrown if the number of replicas requested /// in the ReplicateTo parameter does not match the # of replicas configured on the server.</exception> public bool Observe(string key, ulong cas, bool deletion, ReplicateTo replicateTo, PersistTo persistTo) { var criteria = GetDurabilityCriteria(deletion); var keyMapper = _configInfo.GetKeyMapper(); var vBucket = (IVBucket)keyMapper.MapKey(key); var p = new ObserveParams { Cas = cas, Criteria = criteria, Key = key, PersistTo = persistTo, ReplicateTo = replicateTo, VBucket = vBucket }; p.CheckConfiguredReplicas(); var operation = new Observe(key, vBucket, _transcoder, (uint)_timeout); do { var master = p.VBucket.LocatePrimary(); var result = master.Send(operation); var state = result.Value; if (state.KeyState == p.Criteria.PersistState) { Interlocked.Increment(ref p.PersistedToCount); } if (!deletion && p.HasMutated(state.Cas)) { return false; } //First check if durability has already been met if (p.IsDurabilityMet()) { return true; } //If not check each replica if (CheckReplicas(p, operation)) { return true; } //prepare for another attempt operation = (Observe)operation.Clone(); p.Reset(); } while (!operation.TimedOut()); return false; }
/// <summary> /// Performs an observe event on the durability requirements specified on a key asynchronously /// </summary> /// <param name="key">The key to observe.</param> /// <param name="cas">The 'Check and Set' value of the key.</param> /// <param name="deletion">True if this is a delete operation.</param> /// <param name="replicateTo">The number of replicas that the key must be replicated to to satisfy the durability constraint.</param> /// <param name="persistTo">The number of replicas that the key must be persisted to to satisfy the durability constraint.</param> /// <returns> A <see cref="Task{bool}"/> representing the aynchronous operation.</returns> /// <exception cref="ReplicaNotConfiguredException">Thrown if the number of replicas requested /// in the ReplicateTo parameter does not match the # of replicas configured on the server.</exception> public async Task<bool> ObserveAsync(string key, ulong cas, bool deletion, ReplicateTo replicateTo, PersistTo persistTo) { var criteria = GetDurabilityCriteria(deletion); var keyMapper = _configInfo.GetKeyMapper(); var vBucket = (IVBucket) keyMapper.MapKey(key); var observeParams = new ObserveParams { Cas = cas, Criteria = criteria, Key = key, PersistTo = persistTo, ReplicateTo = replicateTo, VBucket = vBucket }; observeParams.CheckConfiguredReplicas(); var operation = new Observe(key, vBucket, _transcoder, (uint)_timeout); //Used to terminate the loop at the specific timeout using (var cts = new CancellationTokenSource(_timeout)) { //perform the observe operation at the set interval and terminate if not successful by the timeout var task = await ObserveEvery(async p => { //check the master for persistence to disk IServer master; var attempts = 0; while ((master = p.VBucket.LocatePrimary()) == null) { if (attempts++ > 10) { throw new TimeoutException("Could not acquire a server."); } await Task.Delay((int) Math.Pow(2, attempts)); } var result = master.Send(operation); Log.Debug(m => m("Master {0} - {1}", master.EndPoint, result.Value)); var state = result.Value; if (state.KeyState == p.Criteria.PersistState) { Interlocked.Increment(ref p.PersistedToCount); } //Key mutation detected so fail if (p.HasMutated(state.Cas)) { return false; } //Check if durability requirements have been met if (p.IsDurabilityMet()) { return true; } //Run the durability requirement check on each replica var tasks = new List<Task<bool>>(); var replicas = p.GetReplicas(); replicas.ForEach(x => tasks.Add(CheckReplicaAsync(p, operation, x))); //Wait for all tasks to finish await Task.WhenAll(tasks.ToArray()).ContinueOnAnyContext(); var mutated = tasks.All(subtask => subtask.Result); return p.IsDurabilityMet() && !mutated; }, observeParams, operation, _interval, cts.Token).ContinueOnAnyContext(); return task; } }
/// <summary> /// Checks the replicas to see if the key has met the durability constraints defined by the caller. /// </summary> /// <param name="observeParams">The observe parameters.</param> /// <param name="operation">The operation observe operation reference; will be cloned if reused.</param> /// <param name="replicateTo">The replication durability that must be met.</param> /// <param name="persistTo">The persistence durbaility that must be met.</param> /// <returns></returns> bool CheckReplicas(ObserveParams observeParams, Observe operation, ReplicateTo replicateTo, PersistTo persistTo) { //Get the candidate replicas, if none are defined that match the specified durability return false. var replicas = GetReplicas(observeParams.VBucket, replicateTo, persistTo); if (replicas.Count < (int)replicateTo) { return false; } //Check each replica to see if has met the durability constraints specified. A mutation means we failed. var mutated = replicas.All(index => CheckReplica(observeParams, operation, index)); return observeParams.IsDurabilityMet() && !mutated; }
/// <summary> /// Checks the replicas to see if the key has met the durability constraints defined by the caller. /// </summary> /// <param name="observeParams">The observe parameters.</param> /// <param name="operation">The operation observe operation reference; will be cloned if reused.</param> /// <returns></returns> bool CheckReplicas(ObserveParams observeParams, Observe operation) { //Get the candidate replicas, if none are defined that match the specified durability return false. var replicas = observeParams.GetReplicas(); //Check each replica to see if has met the durability constraints specified. A mutation means we failed. var mutated = replicas.All(index => CheckReplica(observeParams, operation, index)); return observeParams.IsDurabilityMet() && !mutated; }
/// <summary> /// Checks the replica at a given replicaIndex for the durability constraints. /// </summary> /// <param name="observeParams">The observe parameters - stateful - gather info with each request.</param> /// <param name="operation">The observe operation.</param> /// <param name="replicaIndex">Index of the replica.</param> /// <returns>True if the key has not mutated.</returns> static bool CheckReplica(ObserveParams observeParams, Observe operation, int replicaIndex) { //clone the operation since we already checked the primary and we want to maintain internal state (opaque, timer, etc) operation = (Observe)operation.Clone(); var replica = observeParams.VBucket.LocateReplica(replicaIndex); var result = replica.Send(operation); //Check the result and update the counters var state = result.Value; if (state.KeyState == observeParams.Criteria.PersistState) { Interlocked.Increment(ref observeParams.ReplicatedToCount); Interlocked.Increment(ref observeParams.PersistedToCount); } else if (state.KeyState == observeParams.Criteria.ReplicateState) { Interlocked.Increment(ref observeParams.ReplicatedToCount); } return !observeParams.HasMutated(state.Cas); }
/// <summary> /// Asynchronously checks the replications status of a key. /// </summary> /// <param name="observeParams">The <see cref="ObserveParams"/> object.</param> /// <param name="operation">The Observe operation.</param> /// <param name="replicaIndex">The replicaIndex of the replica within the <see cref="IVBucket"/></param> /// <returns>True if the durability requirements specified by <see cref="PersistTo"/> and <see cref="ReplicateTo"/> have been satisfied.</returns> static async Task<bool> CheckReplicaAsync(ObserveParams observeParams, Observe operation, int replicaIndex) { Log.Debug(m=>m("checking replica {0}", replicaIndex)); if (observeParams.IsDurabilityMet()) return true; //clone the operation since we already checked the primary and we want to maintain internal state (opaque, timer, etc) operation = (Observe)operation.Clone(); var replica = observeParams.VBucket.LocateReplica(replicaIndex); var result = await Task.Run(()=>replica.Send(operation)).ContinueOnAnyContext(); Log.Debug(m=>m("Replica {0} - {1} [0]", replica.EndPoint, result.Value, replicaIndex)); var state = result.Value; if (state.KeyState == observeParams.Criteria.PersistState) { Interlocked.Increment(ref observeParams.ReplicatedToCount); Interlocked.Increment(ref observeParams.PersistedToCount); } else if (state.KeyState == observeParams.Criteria.ReplicateState) { Interlocked.Increment(ref observeParams.ReplicatedToCount); } return !observeParams.HasMutated(state.Cas); }
private async Task<bool> CheckPersistToAsync(ObserveParams observeParams) { if (observeParams.PersistTo == PersistTo.Zero) return true; var tcs = new TaskCompletionSource<IOperationResult<ObserveState>>(); var operation = new Observe(observeParams.Key, observeParams.VBucket, _clusterController.Transcoder, (uint)_timeout); operation.Completed = CallbackFactory.CompletedFuncForRetry(_pending, _clusterController, tcs); _pending.TryAdd(operation.Opaque, operation); var server = await GetServerAsync(observeParams); await server.SendAsync(operation).ContinueOnAnyContext(); var result = await tcs.Task.ContinueOnAnyContext(); Log.Debug(m => m("Master {0} - {1} key:{2}", server.EndPoint, result.Value, observeParams.Key)); var state = result.Value; if (state.KeyState == observeParams.Criteria.PersistState) { Interlocked.Increment(ref observeParams.PersistedToCount); } //Key mutation detected so fail if (observeParams.HasMutated(state.Cas)) { Log.Debug(m => m("Mutation detected {0} - {1} - opaque: {2} key:{3}",server.EndPoint, result.Value, operation.Opaque, observeParams.Key)); throw new DocumentMutationException(string.Format("Document mutation detected during observe for key '{0}'", observeParams.Key)); } //Check if durability requirements have been met if (observeParams.IsDurabilityMet()) { Log.Debug(m => m("Durability met {0} - {1} - opaque: {2} key:{3}", server.EndPoint, result.Value, operation.Opaque, observeParams.Key)); return true; } return false; }
/// <summary> /// Asynchronously checks the replications status of a key. /// </summary> /// <param name="observeParams">The <see cref="ObserveParams"/> object.</param> /// <param name="replicaIndex">The replicaIndex of the replica within the <see cref="IVBucket"/></param> /// <returns>True if the durability requirements specified by <see cref="PersistTo"/> and <see cref="ReplicateTo"/> have been satisfied.</returns> private async Task<bool> CheckReplicaAsync(ObserveParams observeParams, int replicaIndex) { if (observeParams.IsDurabilityMet()) return true; var operation = new Observe(observeParams.Key, observeParams.VBucket, _clusterController.Transcoder, (uint)_timeout); var tcs = new TaskCompletionSource<IOperationResult<ObserveState>>(); operation.Completed = CallbackFactory.CompletedFuncForRetry(_pending, _clusterController, tcs); _pending.TryAdd(operation.Opaque, operation); var replica = observeParams.VBucket.LocateReplica(replicaIndex); await replica.SendAsync(operation).ContinueOnAnyContext(); var result = await tcs.Task.ContinueOnAnyContext(); Log.Debug(m=>m("Replica {0} - {1} {2} - opaque: {3} key:{4}", replica.EndPoint, result.Value.KeyState, replicaIndex, operation.Opaque, observeParams.Key)); var state = result.Value; if (state.KeyState == observeParams.Criteria.PersistState) { Interlocked.Increment(ref observeParams.ReplicatedToCount); Interlocked.Increment(ref observeParams.PersistedToCount); } else if (state.KeyState == observeParams.Criteria.ReplicateState) { Interlocked.Increment(ref observeParams.ReplicatedToCount); } return !observeParams.HasMutated(state.Cas); }