/// <summary> /// Try to get the value from cache, with logging. /// </summary> private bool TryGetOrAdd(CachingQueryRunnerKey key, MessageContext msg, out CachingQueryRunnerValue result, Func <CachingQueryRunnerKey, CachingQueryRunnerValue> valueFactory) { bool foundValue; foundValue = Cache.TryGetOrAdd(key, out result, valueFactory); msg.Append(() => "CachingQueryRunner key:" + key); if (foundValue) { var cacheValue = result; msg.Append(() => "CachingQueryRunner cache hit"); msg.Append(() => $"Entry originally cached at {cacheValue.CacheTime}"); } else { msg.Append(() => "CachingQueryRunner cache miss"); } return(foundValue); }
/// <summary> /// Create cache keys /// </summary> /// <param name="query">The query</param> /// <param name="settings">The query settings</param> /// <param name="perUserKey">True if the key is for a specific user; or false if it is to be shared across users.</param> /// <returns>The cache key</returns> private CachingQueryRunnerKey CreateCacheKeyImpl(StructuredQuery query, QuerySettings settings, bool perUserKey) { // Get a user-set key // (Users may share the same report SQL if they have the same set of read-rules) UserRuleSet userRuleSet = null; if (settings.RunAsUser != 0) { userRuleSet = UserRuleSetProvider.GetUserRuleSet(settings.RunAsUser, Permissions.Read); if (userRuleSet == null) { throw new InvalidOperationException("Expected userRuleSet"); // Assert false } } // Create cache key // Cached with userId = -1 if the user long userId = perUserKey ? settings.RunAsUser : ShareAcrossUsersCacheKey; var key = new CachingQueryRunnerKey(query, settings, userRuleSet, userId); return(key); }
/// <summary> /// Returns a suitable key for comparing query runs. /// </summary> /// <returns>A key, or null if the query should not be cached.</returns> private CachingQueryRunnerKey CreateCacheKeyAndQuery(StructuredQuery query, QuerySettings settings, out QueryBuild builtQuery) { // Build the SQL for the query // Note: unfortunately this may mutate the query, so keep a copy StructuredQuery queryCopy = query.DeepCopy( ); builtQuery = BuildQueryImpl(queryCopy, settings); // Check if query can even participate in cache bool doNotCacheResult = builtQuery.SqlIsUncacheable || builtQuery.DataIsUncacheable || !CachingQueryRunnerKey.DoesRequestAllowForCaching(query, settings); if (doNotCacheResult) { return(null); } // If we get to this point, then the cache is definitely participating // Determine the cache key - either shared across users, or specific to the current user. CachingQueryRunnerKey key = CreateCacheKeyImpl(query, settings, builtQuery.DataReliesOnCurrentUser); return(key); }