/// <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); }
public CustomDataReader(ICacheTable chacheTable) { _chacheTable = chacheTable; _this = this; }
/// <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); }
public ExpressionDataReader(ICacheTable chacheTable, IExpression expression) { _chacheTable = chacheTable; _expression = expression; _this = this; }