/// <summary> /// Tries to lock the given key. /// </summary> /// <param name="key">The key to lock.</param> /// <param name="luaScript">The lua script to lock the key.</param> /// <param name="extraKeys">The extra keys that will be provided to the <paramref name="luaScript"/></param> /// <param name="extraValues">The extra values that will be provided to the <paramref name="luaScript"/></param> /// <returns>The lock value used to lock the key.</returns> /// <exception cref="CacheException">Thrown if the lock was not acquired.</exception> public string Lock(string key, string luaScript, RedisKey[] extraKeys, RedisValue[] extraValues) { if (key == null) { throw new ArgumentNullException(nameof(key)); } var lockKey = $"{key}{_lockKeySuffix}"; string Context() => lockKey; return(_retryPolicy.Execute(() => { var lockValue = _lockValueProvider.GetValue(); if (!string.IsNullOrEmpty(luaScript)) { var keys = new RedisKey[] { lockKey }; if (extraKeys != null) { keys = keys.Concat(extraKeys).ToArray(); } var values = new RedisValue[] { lockValue, (long)_lockTimeout.TotalMilliseconds }; if (extraValues != null) { values = values.Concat(extraValues).ToArray(); } var result = (RedisValue[])_database.ScriptEvaluate(luaScript, keys, values); if ((bool)result[0]) { return lockValue; } } else if (_database.LockTake(lockKey, lockValue, _lockTimeout)) { return lockValue; } return null; // retry }, Context)); }