public IObservable <Change <TObject, TKey> > Watch(TKey key) { return(Observable.Create <Change <TObject, TKey> > ( observer => { lock (_locker) { //Create or find the existing subscribers var existing = _subscribers.Lookup(key); SubjectWithRefCount <Change <TObject, TKey> > subject; if (existing.HasValue) { subject = existing.Value; } else { subject = new SubjectWithRefCount <Change <TObject, TKey> >(new ReplaySubject <Change <TObject, TKey> >(1)); var initial = _source.Lookup(key); if (initial.HasValue) { var update = new Change <TObject, TKey>(ChangeReason.Add, key, initial.Value); subject.OnNext(update); } _subscribers.Edit(updater => updater.AddOrUpdate(subject, key)); } //set up subscription var subscriber = subject.Subscribe(observer); return Disposable.Create(() => { //lock to ensure no race condition where the same key could be subscribed //to whilst disposal is taking place lock (_locker) { subscriber.Dispose(); if (subject.RefCount == 0) { _subscribers.Edit(updater => updater.Remove(key)); } } }); } })); }
public IObservable <IChangeSet <TObject, TKey> > ExpireAfter() { return(Observable.Create <IChangeSet <TObject, TKey> >(observer => { var cache = new IntermediateCache <TObject, TKey>(_source); var published = cache.Connect().Publish(); var subscriber = published.SubscribeSafe(observer); var autoRemover = published.ForExpiry(_timeSelector, _interval, _scheduler) .Finally(observer.OnCompleted) .Subscribe(keys => { try { cache.Edit(updater => updater.Remove(keys.Select(kv => kv.Key))); } catch (Exception ex) { observer.OnError(ex); } }); var connected = published.Connect(); return Disposable.Create(() => { connected.Dispose(); subscriber.Dispose(); autoRemover.Dispose(); cache.Dispose(); }); })); }
public IObservable <IChangeSet <TObject, TKey> > Run() { return(Observable.Create <IChangeSet <TObject, TKey> >(observer => { var sizeLimiter = new SizeLimiter <TObject, TKey>(_size); var root = new IntermediateCache <TObject, TKey>(_source); var subscriber = root.Connect() .Transform((t, v) => new ExpirableItem <TObject, TKey>(t, v, DateTime.Now)) .Select(changes => { var result = sizeLimiter.Change(changes); var removes = result.Where(c => c.Reason == ChangeReason.Remove); root.Edit(updater => removes.ForEach(c => updater.Remove(c.Key))); return result; }) .Finally(observer.OnCompleted) .SubscribeSafe(observer); return Disposable.Create(() => { subscriber.Dispose(); root.Dispose(); }); })); }
internal void Update(Action <IIntermediateUpdater <TObject, TKey> > updateAction) { _cache.Edit(updateAction); }