예제 #1
0
 public void CopyTo(ConsulDependencies other)
 {
     other.Keys.UnionWith(Keys);
     other.ConfigurationKeys.UnionWith(ConfigurationKeys);
     other.KeyPrefixes.UnionWith(KeyPrefixes);
     other.Services.UnionWith(Services);
 }
예제 #2
0
        public async Task <ConsulState> GetDependenciesAsync(ConsulDependencies dependencies)
        {
            var serviceTasks      = dependencies.Services.Select(GetServiceAsync);
            var keyTasks          = dependencies.Keys.Select(GetKeyAsync);
            var configKeyTasks    = dependencies.ConfigurationKeys.Select(GetKeyAsync);
            var keyRecursiveTasks = dependencies.KeyPrefixes.Select(GetKeyRecursiveAsync);

            await Task.WhenAll(serviceTasks.Cast <Task>().Concat(keyTasks).Concat(configKeyTasks).Concat(keyRecursiveTasks));

            var services = serviceTasks.Select(t => t.Result)
                           .Where(s => s != null)
                           .ToImmutableDictionary(s => s.Name);

            var keys = new KeyValueStore(keyTasks
                                         .Select(t => t.Result)
                                         .Where(k => k != null)
                                         .Concat(configKeyTasks.Select(x => x.Result))
                                         .Concat(keyRecursiveTasks.SelectMany(t => t.Result)));

            var missingKeyPrefixes = dependencies.KeyPrefixes
                                     .Where(prefix => !keys.ContainsKeyStartingWith(prefix))
                                     .ToImmutableHashSet();

            return(new ConsulState(services, keys, missingKeyPrefixes));
        }
예제 #3
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)));
        }
예제 #4
0
 public bool SatisfiesAll(ConsulDependencies consulDependencies)
 {
     return(consulDependencies.Services.IsSubsetOf(_services.Keys) &&
            consulDependencies.Keys.IsSubsetOf(KVStore.Select(s => s.FullKey)) &&
            consulDependencies.KeyPrefixes.All(p => KVStore.Any(k => k.FullKey.StartsWith(p)) || _missingKeyPrefixes.Contains(p)));
 }