Example #1
0
        /// <summary>
        /// Fetches an item through cache - if the item exists and satisfies the `ICacheParams` (and optional `fFilter` functor) then it is immediately returned
        /// to the caller. Otherwise, calls the `fFetch` functor to perform the actual fetch of a value by key, and then puts the result in cache
        /// according to `ICacheParams`
        /// </summary>
        /// <typeparam name="TKey">Type of key</typeparam>
        /// <typeparam name="TResult">Type of the result value</typeparam>
        /// <param name="cache">Non-null ICache instance to operate on</param>
        /// <param name="key">Key value</param>
        /// <param name="tblCache">Name of cache table</param>
        /// <param name="caching">Caching options, or null for defaults</param>
        /// <param name="fFetch">Required functor that performs actual fetch when the value is NOT found in cache</param>
        /// <param name="fFilter">Optional functor - additional filter applied to existing values</param>
        /// <returns>Cached reference type value, or null if not found or absent</returns>
        public static TResult FetchThrough <TKey, TResult>(this ICache cache,
                                                           TKey key,
                                                           string tblCache,
                                                           ICacheParams caching,
                                                           Func <TKey, TResult> fFetch,
                                                           Func <TKey, TResult, TResult> fFilter = null) where TResult : class
        {
            cache.NonNull(nameof(cache));

            ICacheTable <TKey> tbl = null;

            if (caching == null)
            {
                caching = CacheParams.DefaultCache;
            }

            if (caching.ReadCacheMaxAgeSec >= 0 || caching.WriteCacheMaxAgeSec >= 0)
            {
                tbl = cache.GetOrCreateTable <TKey>(tblCache);
            }

            TResult result = null;

            if (caching.ReadCacheMaxAgeSec >= 0)
            {
                var cached = tbl.Get(key, caching.ReadCacheMaxAgeSec);
                if (cached is AbsentValue)
                {
                    return(null);
                }
                else
                {
                    result = cached as TResult;
                }

                if (fFilter != null)
                {
                    result = fFilter(key, result);
                }
            }

            if (result != null)
            {
                return(result);
            }

            result = fFetch.NonNull(nameof(fFetch))(key);

            if (result == null && !caching.CacheAbsentData)
            {
                return(null);
            }

            var wAge = caching.WriteCacheMaxAgeSec;

            if (wAge >= 0)
            {
                tbl.Put(key, (object)result ?? AbsentValue.Instance, wAge > 0 ? wAge : (int?)null, caching.WriteCachePriority);
            }

            return(result);
        }
Example #2
0
 public CustomDataReader(ICacheTable chacheTable)
 {
     _chacheTable = chacheTable;
     _this        = this;
 }
Example #3
0
        /// <summary>
        /// Asynchronously fetches an item through cache - if the item exists and satisfies the `ICacheParams` (and optional `fFilter` functor) then it is
        /// immediately (synchronously) returned to the caller. Otherwise, calls the `fFetch` async functor to perform the actual fetch of a value by key,
        /// and then puts the result in cache according to `ICacheParams`
        /// </summary>
        /// <typeparam name="TKey">Type of key</typeparam>
        /// <typeparam name="TResult">Type of the result value</typeparam>
        /// <param name="cache">Non-null ICache instance to operate on</param>
        /// <param name="key">Key value</param>
        /// <param name="tblCache">Name of cache table</param>
        /// <param name="caching">Caching options, or null for defaults</param>
        /// <param name="fFetch">Required async functor that performs actual fetch when the value is NOT found in cache</param>
        /// <param name="fFilter">Optional functor - additional filter applied to existing values</param>
        /// <param name="extraPut">Optional functor (cache, TKey, TResult, ICacheParams) which can be used to add the piled value to other cache tables (indexes) </param>
        /// <returns>Cached reference type value, or null if not found or absent</returns>
        public static async Task <TResult> FetchThroughAsync <TKey, TResult>(this ICache cache,
                                                                             TKey key,
                                                                             string tblCache,
                                                                             ICacheParams caching,
                                                                             Func <TKey, Task <TResult> > fFetch,
                                                                             Func <TKey, TResult, TResult> fFilter = null,
                                                                             Action <ICache, TKey, TResult, ICacheParams> extraPut = null
                                                                             ) where TResult : class
        {
            cache.NonNull(nameof(cache));

            ICacheTable <TKey> tbl = null;

            if (caching == null)
            {
                caching = CacheParams.DefaultCache;
            }

            if (caching.ReadCacheMaxAgeSec >= 0 || caching.WriteCacheMaxAgeSec >= 0)
            {
                tbl = cache.GetOrCreateTable <TKey>(tblCache);
            }

            TResult result = null;

            if (caching.ReadCacheMaxAgeSec >= 0)
            {
                var cached = tbl.Get(key, caching.ReadCacheMaxAgeSec);
                if (cached is AbsentValue)
                {
                    return(null);
                }
                else
                {
                    result = cached as TResult;
                }

                if (fFilter != null)
                {
                    result = fFilter(key, result);
                }
            }

            if (result != null)
            {
                return(result);
            }

            result = await fFetch.NonNull(nameof(fFetch))(key);//<-- only fFetch is IO-bound hence asynchronous

            if (result == null && !caching.CacheAbsentData)
            {
                return(null);
            }

            var wAge = caching.WriteCacheMaxAgeSec;

            if (wAge >= 0)
            {
                var pr = tbl.Put(key, (object)result ?? AbsentValue.Instance, out var ptr, wAge > 0 ? wAge : (int?)null, caching.WriteCachePriority);
                if (pr != PutResult.Collision && ptr.Valid)
                {
                    extraPut?.Invoke(cache, key, result, caching);
                }
            }

            return(result);
        }
Example #4
0
 public ExpressionDataReader(ICacheTable chacheTable, IExpression expression)
 {
     _chacheTable = chacheTable;
     _expression  = expression;
     _this        = this;
 }