/// <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);
}
}
}