示例#1
0
 public bool TryUpdateKVNode(KeyValueNode kvNode, out ConsulState updatedState)
 {
     if (_kvStore.TryUpdate(kvNode, out var updatedKvStore))
     {
         updatedState = new ConsulState(_services, updatedKvStore, _missingKeyPrefixes);
         return(true);
     }
     updatedState = null;
     return(false);
 }
示例#2
0
        public bool TryUpdateService(Service service, out ConsulState updatedState)
        {
            if (_services.TryGetValue(service.Name, out var existingService) && existingService.Equals(service))
            {
                updatedState = null;
                return(false);
            }

            updatedState = new ConsulState(_services.SetItem(service.Name, service), _kvStore, _missingKeyPrefixes);
            return(true);
        }
示例#3
0
        public bool TryMarkKeyPrefixAsMissingOrEmpty(string keyPrefix, out ConsulState updatedState)
        {
            if (_missingKeyPrefixes.Contains(keyPrefix))
            {
                updatedState = null;
                return(false);
            }
            var kvStore = _kvStore;

            if (_kvStore.TryRemoveKeysStartingWith(keyPrefix, out var updatedKvStore))
            {
                kvStore = updatedKvStore;
            }
            updatedState = new ConsulState(_services, kvStore, _missingKeyPrefixes.Add(keyPrefix));
            return(true);
        }
示例#4
0
        public bool TryUpdateKVNodes(IEnumerable <KeyValueNode> kvNodes, out ConsulState updatedState)
        {
            var missingKeyPrefixes = _missingKeyPrefixes;

            if (kvNodes.Any())
            {
                var noLongerMissingKeyPrefix = _missingKeyPrefixes.FirstOrDefault(keyPrefix => kvNodes.First().FullKey.StartsWith(keyPrefix));
                if (noLongerMissingKeyPrefix != null)
                {
                    missingKeyPrefixes = _missingKeyPrefixes.Remove(noLongerMissingKeyPrefix);
                }
            }

            if (_kvStore.TryUpdate(kvNodes, out var updatedKvStore))
            {
                updatedState = new ConsulState(_services, updatedKvStore, missingKeyPrefixes);
                return(true);
            }
            updatedState = null;
            return(false);
        }
示例#5
0
        public IObservable <ConsulState> ObserveDependencies(ConsulDependencies dependencies)
        {
            var consulState = new ConsulState();
            var updateMutex = new object();

            void WrapUpdate(string operationName, Action <EventContext> tryUpdate)
            {
                var eventContext = new EventContext("ConsulRx.ConsulState", operationName);

                try
                {
                    lock (updateMutex)
                    {
                        tryUpdate(eventContext);
                    }
                }
                catch (Exception ex)
                {
                    eventContext.IncludeException(ex);
                    throw;
                }
                finally
                {
                    eventContext.Dispose();
                }
            }

            var consulStateObservable = Observable.Create <ConsulState>(o =>
            {
                var compositeDisposable = new CompositeDisposable
                {
                    this.ObserveServices(dependencies.Services)
                    .Select(services => services.ToService())
                    .Subscribe(service =>
                    {
                        WrapUpdate("UpdateService", eventContext =>
                        {
                            eventContext["ServiceName"] = service.Name;
                            bool alreadyExisted         = consulState.ContainsService(service.Name);
                            if (consulState.TryUpdateService(service, out var updatedState))
                            {
                                eventContext["UpdateType"] = alreadyExisted ? "Update" : "Add";
                                consulState = updatedState;
                                o.OnNext(consulState);
                            }
                            else
                            {
                                eventContext["UpdateType"] = "Noop";
                            }
                        });
                    }, o.OnError),
                    this.ObserveKeys(dependencies.Keys)
                    .Select(kv => kv.ToKeyValueNode())
                    .Subscribe(kvNode =>
                    {
                        WrapUpdate("UpdateKey", eventContext =>
                        {
                            eventContext["Key"]   = kvNode.FullKey;
                            eventContext["Value"] = kvNode.Value;
                            bool alreadyExisted   = consulState.ContainsKey(kvNode.FullKey);
                            if (consulState.TryUpdateKVNode(kvNode, out var updatedState))
                            {
                                eventContext["UpdateType"] = alreadyExisted ? "Update" : "Add";
                                consulState = updatedState;
                                o.OnNext(consulState);
                            }
                            else
                            {
                                eventContext["UpdateType"] = "Noop";
                            }
                        });
                    }, o.OnError),
                    this.ObserveKeysRecursive(dependencies.KeyPrefixes)
                    .Subscribe(kv =>
                    {
                        WrapUpdate("UpdateKeys", eventContext =>
                        {
                            eventContext["KeyPrefix"]     = kv.KeyPrefix;
                            eventContext["ChildKeyCount"] = kv.Result.Response?.Length ?? 0;
                            if (kv.Result.Response == null || !kv.Result.Response.Any())
                            {
                                if (consulState.TryMarkKeyPrefixAsMissingOrEmpty(kv.KeyPrefix, out var updatedState)
                                    )
                                {
                                    eventContext["UpdateType"] = "MarkAsMissing";
                                    consulState = updatedState;
                                    o.OnNext(consulState);
                                }
                                else
                                {
                                    eventContext["UpdateType"] = "Noop";
                                }
                            }
                            else
                            {
                                var kvNodes         = kv.ToKeyValueNodes();
                                bool alreadyExisted = consulState.ContainsKeyStartingWith(kv.KeyPrefix);
                                if (consulState.TryUpdateKVNodes(kvNodes, out var updatedState))
                                {
                                    eventContext["UpdateType"] = alreadyExisted ? "Update" : "Add";
                                    consulState = updatedState;
                                    o.OnNext(consulState);
                                }
                                else
                                {
                                    eventContext["UpdateType"] = "Noop";
                                }
                            }
                        });
                    }, o.OnError)
                };

                return(compositeDisposable);
            });


            return(consulStateObservable.Where(s => s.SatisfiesAll(dependencies)));
        }