/// <summary>
 /// Disable all calls to execute on resource. Default data is always returned for
 /// this resource when disabled.
 /// </summary>
 /// <param name="resourceKey">The unique key for the resource.</param>
 public void DisableResource(string resourceKey)
 {
     _failCountCache.Insert(resourceKey, failCountLimit * 2, manualDisableTimeout, null, null);
 }
        /// <summary>
        /// Execute any function without parameters and return defined type of result.
        /// </summary>
        /// <typeparam name="TResult">Return type.</typeparam>
        /// <param name="key">The string key of the item.</param>
        /// <param name="methodToCall">The method that is called to fetch data.</param>
        /// <param name="defaultResult">If cache fetching and methodToCall fails to return data return this value.</param>
        /// <param name="timeout">The time to store data in the cache before a new fetch is done.</param>
        /// <param name="cacheKeys">The dependencies to other cached items, idetified by their keys.</param>
        /// <param name="masterKeys">The master keys that we depend upon. Master keys are used as markers to set up common dependencies without having to create the cache entries first.</param>
        /// <param name="resourceKey">Resource name used in Disable() call.</param>
        /// <returns>TResult type defined in the call.</returns>
        public TResult ExecuteAndCache <TResult>(string key, List <string> cacheKeys, List <string> masterKeys, Func <TResult> methodToCall, TResult defaultResult, TimeSpan timeout, string resourceKey)
        {
            TResult cachedResult;
            bool    manuallyDisabled;

            if (ResourceIsDisabled(resourceKey, out manuallyDisabled))
            {
                if (manuallyDisabled)
                {
                    return(defaultResult);
                }
                return(GetCachedOrDefault(key, _dataCache, defaultResult));
            }

            // Check for fast return, first check if value has timed out
            if (_dataTimeoutCache.Get(key) != null)
            {
                if (TryGetCached(key, _dataCache, out cachedResult))
                {
                    return(cachedResult);
                }
            }

            // Cache has timed out. First mark that fetching is in progress
            if (_fetchFlagCache.AddIfNotExists(key, 1, execTimeout, cacheKeys, masterKeys))
            {
                try
                {
                    try
                    {
                        // Fetch new value
                        var newValue = methodToCall();
                        _dataCache.Insert(key, newValue, new TimeSpan(timeout.Ticks + Math.Max(timeout.Ticks, oldDataMaxTimeout.Ticks)), cacheKeys, masterKeys);
                        _dataTimeoutCache.Insert(key, 1, timeout, cacheKeys, masterKeys);
                        return(newValue);
                    }
                    catch (Exception e)
                    {
                        Log.Error("Failed to execute on resource: " + resourceKey, e);
                        IncFailCount(resourceKey);
                        if (ResourceIsDisabled(resourceKey))
                        {
                            Log.ErrorFormat("Resource {0} is auto disabled for {1} seconds.", resourceKey, failCountTimeout.TotalSeconds);
                        }

                        // Remove timeout item because no new data was stored.
                        _dataTimeoutCache.Remove(key);

                        // Something went wrong return default
                        return(defaultResult);
                    }
                }
                finally
                {
                    _fetchFlagCache.Remove(key);
                }
            }

            // The fetching is already in progress, return existing data
            if (TryGetCachedWithWait(key, _dataCache, out cachedResult))
            {
                return(cachedResult);
            }
            return(defaultResult);
        }