-
Notifications
You must be signed in to change notification settings - Fork 46
/
Copy pathRedisExtensions.cs
73 lines (63 loc) · 2.54 KB
/
RedisExtensions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
using System;
using System.Threading.Tasks;
using StackExchange.Redis;
namespace Gofer.NET
{
public static class RedisExtensions
{
/// <summary>
/// Blocks for blockingTimeout amount of time, and tries to take the lock at an interval of tryLockInterval.
/// If the lock cannot be obtained before the timeout, throws an exception.
/// </summary>
/// <exception cref="ApplicationException">
/// Thrown if the attempt to lock the resource takes longer than blockingTimeout.
/// </exception>
public static async Task<RedisLock> LockBlockingAsync(this IConnectionMultiplexer redis,
string key,
TimeSpan? duration=null,
TimeSpan? blockingTimeout=null,
TimeSpan? tryLockInterval=null,
string token=null)
{
duration = duration ?? TimeSpan.FromMinutes(5);
blockingTimeout = blockingTimeout ?? TimeSpan.FromSeconds(60);
tryLockInterval = tryLockInterval ?? TimeSpan.FromMilliseconds(200);
RedisValue actualToken = token ?? Guid.NewGuid().ToString();
var db = redis.GetDatabase();
var startTime = DateTime.Now;
while (true)
{
if (await db.LockTakeAsync(key, actualToken, duration.Value))
{
return new RedisLock(db, key, actualToken);
}
await Task.Delay(tryLockInterval.Value);
if ((DateTime.Now - startTime) >= blockingTimeout)
{
throw new Exception("Unable to lock resource.");
}
}
}
/// <summary>
/// Tries to take a lock, then returns null immediately if it's not successful.
/// </summary>
/// <param name="redis"></param>
/// <param name="key"></param>
/// <param name="duration"></param>
/// <returns></returns>
public static async Task<RedisLock> LockNonBlockingAsync(this IConnectionMultiplexer redis,
string key,
TimeSpan? duration=null,
string token=null)
{
duration = duration ?? TimeSpan.FromMinutes(5);
RedisValue actualToken = token ?? Guid.NewGuid().ToString();
var db = redis.GetDatabase();
if (await db.LockTakeAsync(key, actualToken, duration.Value))
{
return new RedisLock(db, key, actualToken);
}
return null;
}
}
}