Пример #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());
        }
Пример #2
0
 /// <summary>
 /// This method adds a new object to the database and updates the
 /// corresponding index.
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="blobCache">The cache to retrieve the object from.</param>
 /// <param name="key">The key to look up the cache value with.</param>
 /// <param name="item">The item to add to the database</param>
 /// <param name="maxCacheDuration">
 /// The maximum age of a cache object before the object is treated as
 /// expired and unusable. Cache objects older than this will be treated
 /// as a cache miss.
 /// <returns></returns>
 public static IObservable <T> PutAndUpdateIndex <T>(this IBlobCache blobCache,
                                                     string key,
                                                     Func <IObservable <T> > fetchFunc,
                                                     TimeSpan maxCacheDuration)
     where T : CacheItem
 {
     return(Observable.Defer(() =>
     {
         var absoluteExpiration = blobCache.Scheduler.Now + maxCacheDuration;
         return blobCache.GetOrCreateObject(key, () => CacheIndex.Create(key))
         .SelectMany(index => fetchFunc()
                     .Catch <T, Exception>(Observable.Throw <T>)
                     .SelectMany(x => x.Save <T>(blobCache, key, absoluteExpiration))
                     .Do(x => index.AddAndSave(blobCache, key, x, absoluteExpiration))
                     );
     }));
 }
Пример #3
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());
        }