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
                    });
                }
            }
        }
Example #2
0
        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
            }));
        }
Example #3
0
        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
                });
            }
        }
Example #4
0
 // 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);
 }
Example #5
0
        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);
        }
Example #6
0
        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;
 }
Example #9
0
        /// <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));
        }
Example #10
0
 private void DisposeTimers()
 {
     Controller.Dispose();
     Generate.Dispose();
     Detect.Dispose();
     Observe.Dispose();
 }
Example #11
0
        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));
        }
Example #13
0
        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);
        }
Example #15
0
 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);
        }
Example #18
0
        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();
        }
Example #19
0
 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);
        }
Example #22
0
        public async Task AwaitPatternWithEmptySet()
        {
            var x = await Observe.Empty <int>();

            Assert.AreEqual(0, x);

            var y = await Observe.Empty <string>();

            Assert.AreEqual(null, y);
        }
Example #23
0
        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);
        }
Example #24
0
        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);
        }
Example #25
0
        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);
        }
Example #27
0
        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);
        }
Example #31
0
        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);
        }
Example #32
0
        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 }));
        }
Example #33
0
        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 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);
        }
Example #35
0
 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;
            }
        }
Example #41
0
        /// <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);
        }