24
24
25
25
import java .net .InetAddress ;
26
26
import java .net .UnknownHostException ;
27
+ import java .time .Duration ;
27
28
import java .time .Instant ;
29
+ import java .time .temporal .ChronoUnit ;
28
30
import java .util .Optional ;
29
31
30
32
/**
35
37
*/
36
38
public class JedisLockProvider implements LockProvider {
37
39
38
- private static final String keyPrefix = "job-lock" ;
40
+ private static final String KEY_PREFIX = "job-lock" ;
41
+ private static final String ENV_DEFAULT = "default" ;
39
42
40
- private static final String DEFAULT_ENV = "default" ;
43
+ private static final long AT_MOST_HOURS_DEFAULT = 1 ;
44
+
45
+ // Redis Flags
46
+ private static final String SET_IF_NOT_EXIST = "NX" ;
47
+ private static final String SET_EXPIRE_TIME_IN_MS = "PX" ;
41
48
42
49
private JedisPool jedisPool ;
43
50
private String environment ;
51
+ private Duration atMostHoursDefault ;
44
52
45
53
public JedisLockProvider (JedisPool jedisPool ) {
46
- this (jedisPool , DEFAULT_ENV );
54
+ this (jedisPool , ENV_DEFAULT , AT_MOST_HOURS_DEFAULT );
47
55
}
48
56
49
57
public JedisLockProvider (JedisPool jedisPool , String environment ) {
58
+ this (jedisPool , environment , AT_MOST_HOURS_DEFAULT );
59
+ }
60
+
61
+ public JedisLockProvider (JedisPool jedisPool , String environment , long atMostHoursDefault ) {
50
62
this .jedisPool = jedisPool ;
51
63
this .environment = environment ;
64
+ this .atMostHoursDefault = Duration .of (atMostHoursDefault , ChronoUnit .HOURS );
52
65
}
53
66
54
67
@ Override
55
68
public Optional <SimpleLock > lock (LockConfiguration lockConfiguration ) {
56
- long difference = getDifference (lockConfiguration );
57
- if (difference > 0 ) {
58
- String key = buildKey (lockConfiguration .getName (), this .environment );
59
- try (Jedis jedis = jedisPool .getResource ()) {
60
- String rez = jedis .set (key , buildValue (), "NX" , "PX" , difference );
61
- if (rez != null && "OK" .equals (rez )) {
62
- return Optional .of (new RedisLock (key , jedisPool ));
63
- }
69
+ Instant now = Instant .now ();
70
+
71
+ // Get 'furthest out' configured expire time for lock TTL
72
+ long expireTime = Math .max (
73
+ Duration .between (now , lockConfiguration .getLockAtMostUntil ()).toMillis (),
74
+ Duration .between (now , lockConfiguration .getLockAtLeastUntil ()).toMillis ());
75
+
76
+ String key = buildKey (lockConfiguration .getName (), this .environment );
77
+
78
+ try (Jedis jedis = jedisPool .getResource ()) {
79
+ String rez = jedis .set (key ,
80
+ buildValue (),
81
+ SET_IF_NOT_EXIST ,
82
+ SET_EXPIRE_TIME_IN_MS ,
83
+ expireTime < 0 ? atMostHoursDefault .toMillis () : expireTime ); // And if not set, use default
84
+
85
+ if (rez != null && "OK" .equals (rez )) {
86
+ return Optional .of (new RedisLock (key , jedisPool , lockConfiguration ));
64
87
}
65
88
}
66
89
return Optional .empty ();
67
90
}
68
91
69
- long getDifference (LockConfiguration lockConfiguration ) {
70
- long now = Instant .now ().toEpochMilli ();
71
- long mostDiff = lockConfiguration .getLockAtMostUntil ().toEpochMilli () - now ;
72
- long leastDiff = lockConfiguration .getLockAtLeastUntil ().toEpochMilli () - now ;
73
-
74
- long difference = -1 ;
75
- if (mostDiff > 0 && leastDiff > 0 ) {
76
- difference = Math .max (mostDiff , leastDiff );
77
- } else if (mostDiff > 0 && leastDiff <= 0 ) {
78
- difference = mostDiff ;
79
- } else if (mostDiff <= 0 && leastDiff > 0 ) {
80
- difference = leastDiff ;
81
- }
82
- return difference ;
83
- }
84
-
85
92
private static final class RedisLock implements SimpleLock {
86
93
private final String key ;
87
94
private final JedisPool jedisPool ;
95
+ private final LockConfiguration lockConfiguration ;
88
96
89
- private RedisLock (String key , JedisPool jedisPool ) {
97
+ private RedisLock (String key , JedisPool jedisPool , LockConfiguration lockConfiguration ) {
90
98
this .key = key ;
91
99
this .jedisPool = jedisPool ;
100
+ this .lockConfiguration = lockConfiguration ;
92
101
}
93
102
94
103
@ Override
95
104
public void unlock () {
96
- try (Jedis jedis = jedisPool .getResource ()) {
97
- jedis .del (key );
98
- } catch (Exception e ) {
99
- throw new LockException ("Can not remove node" , e );
105
+ Instant now = Instant .now ();
106
+ Instant atLeastUntil = lockConfiguration .getLockAtLeastUntil ();
107
+
108
+ if (now .equals (atLeastUntil ) || now .isAfter (atLeastUntil )) {
109
+ try (Jedis jedis = jedisPool .getResource ()) {
110
+ jedis .del (key );
111
+ } catch (Exception e ) {
112
+ throw new LockException ("Can not remove node" , e );
113
+ }
100
114
}
101
115
}
102
116
}
@@ -110,7 +124,7 @@ protected static String getHostname() {
110
124
}
111
125
112
126
public static String buildKey (String lockName , String env ) {
113
- return String .format ("%s:%s:%s" , keyPrefix , env , lockName );
127
+ return String .format ("%s:%s:%s" , KEY_PREFIX , env , lockName );
114
128
}
115
129
116
130
static String buildValue () {
0 commit comments