Esempio n. 1
0
        static IObservable <T> GetAndFetchLatestFromIndex <T>(this IBlobCache This,
                                                              string key,
                                                              Func <IObservable <T> > fetchFunc,
                                                              Action <T> removedItemsCallback,
                                                              Func <DateTimeOffset, bool> fetchPredicate = null,
                                                              DateTimeOffset?absoluteExpiration          = null,
                                                              bool shouldInvalidateOnError = false)
            where T : CacheItem
        {
            var idx = Observable.Defer(() => This
                                       .GetOrCreateObject(key, () => CacheIndex.Create(key)))
                      .Select(x => x.IndexKey == null ? CacheIndex.Create(key) : x)
                      .Replay()
                      .RefCount();


            var fetch = idx
                        .Select(x => Tuple.Create(x, fetchPredicate == null || !x.Keys.Any() || fetchPredicate(x.UpdatedAt)))
                        .Where(predicateIsTrue => predicateIsTrue.Item2)
                        .Select(x => x.Item1)
                        .Select(index => index.Clear())
                        .SelectMany(index => fetchFunc()
                                    .Catch <T, Exception>(ex =>
            {
                var shouldInvalidate = shouldInvalidateOnError ?
                                       This.InvalidateObject <CacheIndex>(key) :
                                       Observable.Return(Unit.Default);
                return(shouldInvalidate.SelectMany(__ => Observable.Throw <T>(ex)));
            })
                                    .SelectMany(x => x.Save <T>(This, key, absoluteExpiration))
                                    .Do(x => index.Add(key, x))
                                    );

            var cache = idx
                        .SelectMany(index => This.GetObjects <T>(index.Keys.ToList()))
                        .SelectMany(dict => dict.Values);

            return(cache.Merge(fetch)
                   .Finally(async() =>
            {
                var index = await idx;
                await index.Save(This);

                var list = index.OldKeys.Except(index.Keys);
                if (!list.Any())
                {
                    return;
                }
                var removed = await This.GetObjects <T>(list);
                foreach (var d in removed.Values)
                {
                    removedItemsCallback(d);
                }
                await This.InvalidateObjects <T>(list);
            })
                   .Replay().RefCount());
        }
Esempio n. 2
0
        static IObservable <T> GetAndFetchLatestFromIndex <T>(this IBlobCache This,
                                                              string key,
                                                              Func <IObservable <T> > fetchFunc,
                                                              Action <T> removedItemsCallback,
                                                              Func <DateTimeOffset, bool> fetchPredicate = null,
                                                              DateTimeOffset?absoluteExpiration          = null,
                                                              bool shouldInvalidateOnError = false)
            where T : CacheItem
        {
            var fetch = Observable.Defer(() => This.GetOrCreateObject(key, () => CacheIndex.Create(key))
                                         .Select(x => Tuple.Create(x, fetchPredicate == null || !x.Keys.Any() || fetchPredicate(x.UpdatedAt)))
                                         .Where(predicateIsTrue => predicateIsTrue.Item2)
                                         .Select(x => x.Item1)
                                         .SelectMany(index => index.Clear(This, key, absoluteExpiration))
                                         .SelectMany(index =>
            {
                var fetchObs = fetchFunc().Catch <T, Exception>(ex =>
                {
                    var shouldInvalidate = shouldInvalidateOnError ?
                                           This.InvalidateObject <CacheIndex>(key) :
                                           Observable.Return(Unit.Default);
                    return(shouldInvalidate.SelectMany(__ => Observable.Throw <T>(ex)));
                });

                return(fetchObs
                       .SelectMany(x => x.Save <T>(This, key, absoluteExpiration))
                       .Do(x => index.AddAndSave(This, key, x, absoluteExpiration))
                       .Finally(() =>
                {
                    This.GetObjects <T>(index.OldKeys.Except(index.Keys))
                    .Do(dict => This.InvalidateObjects <T>(dict.Keys))
                    .SelectMany(dict => dict.Values)
                    .Do(removedItemsCallback)
                    .Subscribe();
                }));
            }));

            var cache = Observable.Defer(() => This.GetOrCreateObject(key, () => CacheIndex.Create(key))
                                         .SelectMany(index => This.GetObjects <T>(index.Keys))
                                         .SelectMany(dict => dict.Values));

            return(cache.Merge(fetch).Replay().RefCount());
        }
Esempio n. 3
0
 /// <summary>
 /// Remove a range of entities by the provided keys.
 /// </summary>
 /// <param name="keys">Source keys to remove by.</param>
 public virtual async Task RemoveRange<T>(IEnumerable<string> keys) where T : class, IKeyProvider
 {
     await _blobCache.InvalidateObjects<T>(keys);
 }