public IObservable <ResourceEvent <TResource> > GetResource(ResourceStreamType type, TOptions options) { if (!_sharedInformers.TryGetValue(options, out var sharedInformer)) { var optionLockedMasterInformer = _masterInformer.WithOptions(options); sharedInformer = _sharedInformerFactory(optionLockedMasterInformer); _sharedInformers.Add(options, sharedInformer); } return(sharedInformer.GetResource(type)); }
/// <inheritdoc cref="IKubernetesInformer{TResource}"/> public IObservable <ResourceEvent <TResource> > GetResource(ResourceStreamType type) => base.GetResource(type, KubernetesInformerOptions.Default);
public KubernetesInformerEmitter(KubernetesInformer <TResource> parent, KubernetesInformerOptions options, ResourceStreamType type) { _parent = parent; _options = options; _type = type; }
public IObservable <ResourceEvent <TResource> > GetResource(ResourceStreamType type, KubernetesInformerOptions options) { return(new KubernetesInformerEmitter(this, options, type).GetObservable()); }
public IObservable <ResourceEvent <TResource> > GetResource(ResourceStreamType type) { var childScheduler = new EventLoopScheduler(); // dedicated thread for the child on which all messages are syncrhonized return(Observable.Defer(async() => { AddSubscriber(); _logger.LogTrace("Subscriber awaiting cache synchronization before attaching"); var isCacheSynchronized = await _cacheSynchronized.Task; if (!isCacheSynchronized) // really this only happens if the reset is the master completes before first reset, in which case the downstream subscriber gets nothing { return Observable.Empty <ResourceEvent <TResource> >(); } // we use lock to pause any processing of the broadcaster while we're attaching to the stream so proper alignment can be made _logger.LogTrace("Subscriber attaching to broadcaster"); return Observable.Create <ResourceEvent <TResource> >(observer => { var broadcasterAttachment = Disposable.Empty; var cacheSnapshot = _cache.Snapshot(); if (type.HasFlag(ResourceStreamType.List)) { _logger.LogTrace($"Flushing contents of cache version {cacheSnapshot.Version}"); _cache.Values .ToReset(type == ResourceStreamType.ListWatch) .ToObservable() .Concat(Observable.Never <ResourceEvent <TResource> >()) .ObserveOn(Scheduler.Immediate) .Subscribe(observer); } if (type.HasFlag(ResourceStreamType.Watch)) { broadcasterAttachment = _masterObservable // we could be ahead of broadcaster because we initialized from cache which gets updated before the message are sent to broadcaster // this logic realigns us at the correct point with the broadcaster .Do(x => _logger.LogTrace($"Received from broadcaster {x}")) .SkipWhile(x => x.MessageNumber <= cacheSnapshot.Version) .Select(x => x.Value) .Do(x => _logger.LogTrace($"Aligned with broadcaster {x}")) .SubscribeOn(_masterScheduler) .ObserveOn(childScheduler) .Subscribe(observer, () => { _logger.LogTrace("Child OnComplete"); RemoveSubscriber(); }); } else { observer.OnCompleted(); } // let broadcaster know we're done attaching to stream so it can resume it's regular work _logger.LogTrace("Finished attaching to stream - signalling to resume"); lock (_lock) { _waitingSubscribers.Signal(); } return broadcasterAttachment; }) .ObserveOn(childScheduler) .SubscribeOn(childScheduler); }) .SubscribeOn(childScheduler) // ensures that when we attach master observer it's done on child thread, as we plan on awaiting cache synchronization .Do(_ => _logger.LogTrace($"Shared informer out: {_}"))); }
public IObservable <ResourceEvent <TResource> > GetResource(ResourceStreamType type) => _informer.GetResource(type, _options);