public IObservable <List <MarketCatalogue> > SubscribeFilter(CatalogueFilter filter) { IObservable <List <MarketCatalogue> > lookup; if (_catalogues.TryGetValue(filter.FilterId, out lookup)) { return(lookup); } var observable = Observable.Create <List <MarketCatalogue> >( (IObserver <List <MarketCatalogue> > observer) => { _observers.AddOrUpdate(filter.FilterId, observer, (key, existingVal) => existingVal); return(Disposable.Create(() => { CatalogueFilter f; IObserver <List <MarketCatalogue> > ob; IObservable <List <MarketCatalogue> > o; _filters.TryRemove(filter.FilterId, out f); _catalogues.TryRemove(filter.FilterId, out o); _observers.TryRemove(filter.FilterId, out ob); })); }) .Publish() .RefCount(); _filters.AddOrUpdate(filter.FilterId, filter, (key, existingVal) => existingVal); _catalogues.AddOrUpdate(filter.FilterId, observable, (key, existingVal) => existingVal); return(observable); }
private void DoWorkInner(MarketCatalogueFilter key, CatalogueFilter cf) { BetfairServerResponse <List <MarketCatalogue> > book; try { book = _client.ListMarketCatalogue( cf.MarketFilter, cf.Projection, cf.MarketSort, cf.MaxResult).Result; } catch (AggregateException ex) { foreach (var e in ex.Flatten().InnerExceptions) { _logger.Invoke(e, $"key: {key} filterId: {cf.FilterId}"); } return; } if (book.HasError) { foreach (var observer in _observers) { observer.Value.OnError(book.Error); } return; } // we may have fresher data than the response to this request if (book.RequestStart < _latestDataRequestStart && book.LastByte > _latestDataRequestFinish) { return; } //TODO: locking here is per MarketFilter request... but we do multiples requests; 1 per CatalogueFilter... lock (_lockObj) { _latestDataRequestStart = book.RequestStart; _latestDataRequestFinish = book.LastByte; } IObserver <List <MarketCatalogue> > o; if (!_observers.TryGetValue(key, out o)) { return; } //TODO: would we ever need to call OnCompleted... don't think so? //if (someCondition) // o.OnCompleted(); // else o.OnNext(book.Response); }