Example #1
0
        /// <summary>
        /// Returns the time that the key was added to the cache, or returns
        /// null if the key isn't in the cache.
        /// </summary>
        /// <param name="key">The key to return the date for.</param>
        /// <returns>The date the key was created on.</returns>
        public static IObservable <DateTimeOffset?> GetObjectCreatedAt <T>(this IBlobCache This, string key)
        {
            var objCache = This as IObjectBlobCache;

            if (objCache != null)
            {
                return(This.GetCreatedAt(key));
            }

            return(This.GetCreatedAt(key));
        }
Example #2
0
        /// <summary>
        /// This is the non-generic analog of JsonSerializationMixin.GetAndFetchLatest[1]
        /// We shouldn't make modifications to this that alter its behavior from the generic
        /// version. By having this we can keep our two GetAndRefresh methods extremely
        /// similar and thus trust that what works in one will work in the other.
        ///
        /// 1. https://github.com/akavache/Akavache/blob/1b19bb56d/Akavache/Portable/JsonSerializationMixin.cs#L202-L236
        /// </summary>
        static IObservable <byte[]> GetAndFetchLatestBytes(
            this IBlobCache blobCache,
            string key,
            Func <IObservable <byte[]> > fetchFunc,
            Func <DateTimeOffset, bool> fetchPredicate = null,
            DateTimeOffset?absoluteExpiration          = null)
        {
            var fetch = Observable.Defer(() => blobCache.GetCreatedAt(key))
                        .Select(x => fetchPredicate == null || x == null || fetchPredicate(x.Value))
                        .Where(predicateIsTrue => predicateIsTrue)
                        .SelectMany(_ =>
            {
                return(fetchFunc()
                       .SelectMany(x => blobCache.Invalidate(key).Select(__ => x))
                       .SelectMany(x => blobCache.Insert(key, x, absoluteExpiration).Select(__ => x)));
            });

            var result = blobCache.Get(key).Select(x => Tuple.Create(x, true))
                         .Catch(Observable.Return(new Tuple <byte[], bool>(null, false)));

            return(result
                   .SelectMany(x => x.Item2
                    ? Observable.Return(x.Item1)
                    : Observable.Empty <byte[]>())
                   .Concat(fetch)
                   .Replay()
                   .RefCount());
        }
Example #3
0
        /// <summary>
        /// This method attempts to returned a cached value, while
        /// simultaneously calling a Func to return the latest value. When the
        /// latest data comes back, it replaces what was previously in the
        /// cache.
        ///
        /// This method is best suited for loading dynamic data from the
        /// Internet, while still showing the user earlier data.
        ///
        /// This method returns an IObservable that may return *two* results
        /// (first the cached data, then the latest data). Therefore, it's
        /// important for UI applications that in your Subscribe method, you
        /// write the code to merge the second result when it comes in.
        /// </summary>
        /// <param name="key">The key to store the returned result under.</param>
        /// <param name="fetchFunc"></param>
        /// <param name="fetchPredicate">An optional Func to determine whether
        /// the updated item should be fetched. If the cached version isn't found,
        /// this parameter is ignored and the item is always fetched.</param>
        /// <param name="absoluteExpiration">An optional expiration date.</param>
        /// <returns>An Observable stream containing either one or two
        /// results (possibly a cached version, then the latest version)</returns>
        public static IObservable <T> GetAndFetchLatest <T>(this IBlobCache This,
                                                            string key,
                                                            Func <IObservable <T> > fetchFunc,
                                                            Func <DateTimeOffset, bool> fetchPredicate = null,
                                                            DateTimeOffset?absoluteExpiration          = null)
        {
            bool foundItemInCache;
            var  fail = Observable.Defer(() => This.GetCreatedAt(key))
                        .Select(x => fetchPredicate != null && x != null ? fetchPredicate(x.Value) : true)
                        .Where(x => x != false)
                        .SelectMany(_ => fetchFunc())
                        .Finally(() => This.Invalidate(key))
                        .Do(x => This.InsertObject(key, x, absoluteExpiration));

            var result = This.GetObjectAsync <T>(key).Select(x => new Tuple <T, bool>(x, true))
                         .Catch(Observable.Return(new Tuple <T, bool>(default(T), false)));

            return(result.SelectMany(x =>
            {
                foundItemInCache = x.Item2;
                return x.Item2 ?
                Observable.Return(x.Item1) :
                Observable.Empty <T>();
            }).Concat(fail).Multicast(new ReplaySubject <T>()).RefCount());
        }
        public bool ContainsKey(string key)
        {
            var result = blobCache.GetCreatedAt(key).Wait();

            // FIX: Temporarily logging this, as I suspect it of always returning true
            Log.Verbose(TAG, $"ContainsKey: {key} = {result.HasValue}");
            return(result.HasValue);
        }
        /// <summary>
        /// Returns the time that the key was added to the cache, or returns
        /// null if the key isn't in the cache.
        /// </summary>
        /// <typeparam name="T">The type of item to get.</typeparam>
        /// <param name="blobCache">The cache to get the item.</param>
        /// <param name="key">The key to return the date for.</param>
        /// <returns>The date the key was created on.</returns>
        public static IObservable <DateTimeOffset?> GetObjectCreatedAt <T>(this IBlobCache blobCache, string key)
        {
            if (blobCache is IObjectBlobCache objCache)
            {
                return(objCache.GetObjectCreatedAt <T>(key));
            }

            return(blobCache.GetCreatedAt(GetTypePrefixedKey(key, typeof(T))));
        }
Example #6
0
        /// <summary>
        /// Gets a dictionary filled with the specified keys with their corresponding created <see cref="DateTimeOffset"/>
        /// if it's available.
        /// </summary>
        /// <param name="blobCache">The blob cache to extract the values from.</param>
        /// <param name="keys">The keys to get the values for.</param>
        /// <returns>A observable with the specified values.</returns>
        public static IObservable <IDictionary <string, DateTimeOffset?> > GetCreatedAt(this IBlobCache blobCache, IEnumerable <string> keys)
        {
            if (blobCache is IBulkBlobCache bulkCache)
            {
                return(bulkCache.GetCreatedAt(keys));
            }

            return(keys.ToObservable()
                   .SelectMany(x => blobCache.GetCreatedAt(x).Select(y => new { Key = x, Value = y }))
                   .ToDictionary(k => k.Key, v => v.Value));
        }
        /// <summary>
        /// Returns the time that the key was added to the cache, or returns
        /// null if the key isn't in the cache.
        /// </summary>
        /// <param name="key">The key to return the date for.</param>
        /// <returns>The date the key was created on.</returns>
        public static IObservable <DateTimeOffset?> GetObjectCreatedAt <T>(this IBlobCache This, string key)
        {
            var objCache = This as IObjectBlobCache;

            if (objCache != null)
            {
                return(objCache.GetObjectCreatedAt <T>(key));
            }

            return(This.GetCreatedAt(GetTypePrefixedKey(key, typeof(T))));
        }
Example #8
0
        /// <summary>
        /// Returns the time that the key was added to the cache, or returns
        /// null if the key isn't in the cache.
        /// </summary>
        /// <typeparam name="T">The type of item to get.</typeparam>
        /// <param name="blobCache">The cache to get the item.</param>
        /// <param name="key">The key to return the date for.</param>
        /// <returns>The date the key was created on.</returns>
        public static IObservable <DateTimeOffset?> GetObjectCreatedAt <T>(this IBlobCache blobCache, string key)
        {
            if (blobCache is null)
            {
                throw new ArgumentNullException(nameof(blobCache));
            }

            if (blobCache is IObjectBlobCache objCache)
            {
                return(objCache.GetObjectCreatedAt <T>(key));
            }

            return(blobCache.GetCreatedAt(GetTypePrefixedKey(key, typeof(T))));
        }
Example #9
0
        static IObservable <Unit> VacuumIfNecessary(IBlobCache blobCache, bool force = false)
        {
            const string key           = "__Vacuumed";
            var          vauumInterval = TimeSpan.FromDays(30);

            return(Observable.Defer(() => blobCache.GetCreatedAt(key))
                   .Where(lastVacuum => force || !lastVacuum.HasValue || blobCache.Scheduler.Now - lastVacuum.Value > vauumInterval)
                   .SelectMany(Observable.Defer(blobCache.Vacuum))
                   .SelectMany(Observable.Defer(() => blobCache.Insert(key, new byte[] { 1 })))
                   .Catch <Unit, Exception>(ex =>
            {
                log.Error("Could not vacuum image cache", ex);
                return Observable.Return(Unit.Default);
            })
                   .AsCompletion());
        }
 public IObservable <DateTimeOffset?> GetCreatedAt(string key)
 {
     return(_inner.GetCreatedAt(key));
 }
Example #11
0
 public static bool NeedsMigration(IBlobCache blobCache)
 {
     return(blobCache.GetCreatedAt(MigratedKey).Wait() == null);
 }
 public static bool NeedsMigration(IBlobCache blobCache)
 {
     return blobCache.GetCreatedAt(MigratedKey).Wait() == null;
 }