public virtual void Clear()
        {
            log.DebugFormat("clear cache: regionName='{0}'", RegionName);

            try
            {
                var setOfActiveKeysKey = CacheNamespace.GetSetOfActiveKeysKey();
                var db = GetDatabase();
                db.KeyDelete(setOfActiveKeysKey, fireAndForgetFlags);
            }
            catch (Exception e)
            {
                log.ErrorFormat("could not clear cache: regionName='{0}'", RegionName);

                var evtArg = new ExceptionEventArgs(RegionName, RedisCacheMethod.Clear, e);
                options.OnException(this, evtArg);
                if (evtArg.Throw)
                {
                    throw new RedisCacheException(RegionName, "Failed to clear cache. See inner exception.", e);
                }
            }
        }
Пример #2
0
        public async Task ClearCoreAsync(CancellationToken cancellationToken, bool sync = false)
        {
            cancellationToken.ThrowIfNull("cancellationToken");

            if (cancellationToken.IsCancellationRequested)
            {
                return;
            }

            log.Debug("clear cache: regionName='{0}'", RegionName);

            try
            {
                var setOfActiveKeysKey = CacheNamespace.GetSetOfActiveKeysKey();
                var db = GetDatabase();

                if (sync)
                {
                    db.KeyDelete(setOfActiveKeysKey, fireAndForgetFlags);
                }
                else
                {
                    await db.KeyDeleteAsync(setOfActiveKeysKey, fireAndForgetFlags);
                }
            }
            catch (Exception e)
            {
                log.Error("could not clear cache: regionName='{0}'", RegionName);

                var evtArg = new ExceptionEventArgs(RegionName, RedisCacheMethod.Clear, e);
                options.OnException(this, evtArg);
                if (evtArg.Throw)
                {
                    throw new RedisCacheException(RegionName, "Failed to clear cache. See inner exception.", e);
                }
            }
        }
Пример #3
0
        private async Task UnlockCoreAsync(object key, CancellationToken cancellationToken, bool sync = false)
        {
            cancellationToken.ThrowIfNull("cancellationToken");

            if (cancellationToken.IsCancellationRequested)
            {
                return;
            }

            // Use Remove() instead of Get() because we are releasing the lock
            // anyways.
            var lockData = acquiredLocks.Remove(Convert.ToString(key)) as LockData;

            if (lockData == null)
            {
                log.Warn("attempted to unlock '{0}' but a previous lock was not acquired or timed out", key);
                var unlockFailedEventArgs = new UnlockFailedEventArgs(
                    RegionName, key, lockKey: null, lockValue: null
                    );
                options.OnUnlockFailed(this, unlockFailedEventArgs);
                return;
            }

            log.Debug("releasing cache lock: regionName='{0}', key='{1}', lockKey='{2}', lockValue='{3}'",
                      RegionName, lockData.Key, lockData.LockKey, lockData.LockValue
                      );

            try
            {
                var db = GetDatabase();


                var args = new {
                    lockKey   = lockData.LockKey,
                    lockValue = lockData.LockValue
                };

                // Don't use IDatabase.LockRelease() because it uses watch/unwatch
                // where we prefer an atomic operation (via a script).
                var wasLockReleased = sync
                                        ? (bool)db.ScriptEvaluate(unlockScript, args)
                                        : (bool)await db.ScriptEvaluateAsync(unlockScript, args);

                if (!wasLockReleased)
                {
                    log.Warn("attempted to unlock '{0}' but it could not be released (it maybe timed out or was cleared in Redis)", lockData);

                    var unlockFailedEventArgs = new UnlockFailedEventArgs(
                        RegionName, key, lockData.LockKey, lockData.LockValue
                        );
                    options.OnUnlockFailed(this, unlockFailedEventArgs);
                }
            }
            catch (Exception e)
            {
                log.Error("could not release cache lock: regionName='{0}', key='{1}', lockKey='{2}', lockValue='{3}'",
                          RegionName, lockData.Key, lockData.LockKey, lockData.LockValue
                          );

                var evtArg = new ExceptionEventArgs(RegionName, RedisCacheMethod.Unlock, e);
                options.OnException(this, evtArg);
                if (evtArg.Throw)
                {
                    throw new RedisCacheException(RegionName, "Failed to unlock item in cache. See inner exception.", e);
                }
            }
        }
Пример #4
0
        private async Task LockCoreAsync(object key, CancellationToken cancellationToken, bool sync = false)
        {
            cancellationToken.ThrowIfNull("cancellationToken");

            if (cancellationToken.IsCancellationRequested)
            {
                return;
            }

            log.Debug("acquiring cache lock: regionName='{0}', key='{1}'", RegionName, key);

            try
            {
                var lockKey     = CacheNamespace.GetLockKey(key);
                var shouldRetry = options.AcquireLockRetryStrategy.GetShouldRetry();

                var wasLockAcquired      = false;
                var shouldTryAcquireLock = true;

                while (shouldTryAcquireLock)
                {
                    var lockData = new LockData(
                        key: Convert.ToString(key),
                        lockKey: lockKey,
                        // Recalculated each attempt to ensure a unique value.
                        lockValue: options.LockValueFactory.GetLockValue()
                        );

                    bool lockAquired = sync
                                                ? this.TryAcquireLockAsync(lockData, true).ConfigureAwait(false).GetAwaiter().GetResult()
                                                : await this.TryAcquireLockAsync(lockData);

                    if (lockAquired)
                    {
                        wasLockAcquired      = true;
                        shouldTryAcquireLock = false;
                    }
                    else
                    {
                        var shouldRetryArgs = new ShouldRetryAcquireLockArgs(
                            RegionName, lockData.Key, lockData.LockKey,
                            lockData.LockValue, lockTimeout, acquireLockTimeout
                            );
                        shouldTryAcquireLock = shouldRetry(shouldRetryArgs);
                    }
                }

                if (!wasLockAcquired)
                {
                    var lockFailedArgs = new LockFailedEventArgs(
                        RegionName, key, lockKey,
                        lockTimeout, acquireLockTimeout
                        );
                    options.OnLockFailed(this, lockFailedArgs);
                }
            }
            catch (Exception e)
            {
                log.Error("could not acquire cache lock: regionName='{0}', key='{1}'", RegionName, key);

                var evtArg = new ExceptionEventArgs(RegionName, RedisCacheMethod.Lock, e);
                options.OnException(this, evtArg);
                if (evtArg.Throw)
                {
                    throw new RedisCacheException(RegionName, "Failed to lock item in cache. See inner exception.", e);
                }
            }
        }
Пример #5
0
        private async Task <object> GetCoreAsync(object key, CancellationToken cancellationToken, bool sync = false)
        {
            key.ThrowIfNull();
            cancellationToken.ThrowIfNull("cancellationToken");

            if (cancellationToken.IsCancellationRequested)
            {
                return(Task.FromCanceled <object>(cancellationToken));
            }

            log.Debug("get from cache: regionName='{0}', key='{1}'", RegionName, key);

            try
            {
                var cacheKey           = CacheNamespace.GetKey(key);
                var setOfActiveKeysKey = CacheNamespace.GetSetOfActiveKeysKey();

                var db = GetDatabase();

                var args = new {
                    key = cacheKey,
                    setOfActiveKeysKey = setOfActiveKeysKey
                };


                var resultValues = sync
                                        ?(RedisValue[])db.ScriptEvaluate(getScript, args)
                                        :(RedisValue[])await db.ScriptEvaluateAsync(getScript, args);

                if (resultValues[0].IsNullOrEmpty)
                {
                    log.Debug("cache miss: regionName='{0}', key='{1}'", RegionName, key);
                    return(null);
                }
                else
                {
                    var serializedResult = resultValues[0];

                    var deserializedValue = options.Serializer.Deserialize(serializedResult);

                    if (deserializedValue != null && slidingExpiration != RedisCacheConfiguration.NoSlidingExpiration)
                    {
                        var slidingArgs = new {
                            key               = cacheKey,
                            expiration        = expiration.TotalMilliseconds,
                            slidingExpiration = slidingExpiration.TotalMilliseconds
                        };

                        if (sync)
                        {
                            db.ScriptEvaluate(slidingExpirationScript, slidingArgs, fireAndForgetFlags);
                        }
                        else
                        {
                            await db.ScriptEvaluateAsync(slidingExpirationScript, slidingArgs, fireAndForgetFlags);
                        }
                    }

                    return(deserializedValue);
                }
            }
            catch (Exception e) {
                log.Error("could not get from cache: regionName='{0}', key='{1}'", RegionName, key);

                var evtArg = new ExceptionEventArgs(RegionName, RedisCacheMethod.Get, e);
                options.OnException(this, evtArg);
                if (evtArg.Throw)
                {
                    throw new RedisCacheException(RegionName, "Failed to get item from cache. See inner exception.", e);
                }

                return(null);
            }
        }