/// <summary> /// /// </summary> /// <param name="key"></param> public void Unlock(object key) { // 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(); // Don't use IDatabase.LockRelease() because it uses watch/unwatch // where we prefer an atomic operation (via a script). var wasLockReleased = (bool)db.ScriptEvaluate(_unlockScript, new { lockKey = lockData.LockKey, lockValue = lockData.LockValue }); 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); } } }
internal void OnUnlockFailed(RedisCache sender, UnlockFailedEventArgs e) { var onUnlockFailed = UnlockFailed; if (onUnlockFailed == null) { // No-op. } else { onUnlockFailed(sender, e); } }
public virtual void Unlock(object key) { // 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.WarnFormat("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.DebugFormat("releasing cache lock: regionName='{0}', key='{1}', lockKey='{2}', lockValue='{3}'", RegionName, lockData.Key, lockData.LockKey, lockData.LockValue ); try { var db = GetDatabase(); // Don't use IDatabase.LockRelease() because it uses watch/unwatch // where we prefer an atomic operation (via a script). var wasLockReleased = (bool)db.ScriptEvaluate(unlockScript, new { lockKey = lockData.LockKey, lockValue = lockData.LockValue }); if (!wasLockReleased) { log.WarnFormat("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.ErrorFormat("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); } } }
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); } } }