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); }
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); }
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); }
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); }
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))); }