redis_mutex 0.0.1.pre.alpha.pre.10 → 0.0.1.pre.alpha.pre.11

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YmFiZTIwM2E3NTMwMWViY2Q1ZWE2ZGVlNGRhYTNiYjNjNzc4YzMwYQ==
4
+ ZWU4ZmJkOTliYzc4MzFlMDY3ZmE1ZTdjZThjNzM3OTEzNmQ1YTQ0OQ==
5
5
  data.tar.gz: !binary |-
6
- MDc1M2VhZDZjNzkxNWQzNDVjYTAzNjhhMjU1NTAzZDMzNDAwY2I0ZA==
6
+ ZTBlYmMxZjA5YzcxMjQ0N2Q3NDBjYzUwMjRlOWZiMjM4OTVkOGEyNA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NzMyYTRmNDA3NzZhMDFhMmFhZjBhN2M1ZTg4M2RlZWNmYmRmNGU3ZDZhYTYy
10
- MTBkNzYwOTlmNTgwMmZlZTZiZTY1OWVkZjg1NDg5MGEyYjlmMTY0ZTAzMDkz
11
- NWYyNDYwOTBjM2U4ZWEwMDExNjViMDI2NzBlOWM4OGRiMGRlNjg=
9
+ OTRmYWNkY2M3Yjk1ZWRjZjFhMTIwNDA2ODdlODQ4YzQ4ODdiODAwZDcxNjlh
10
+ ZGU4OGNjYjc0MWU3YTIwYTRhMGQxMmQzOThmZWRjM2Y2MzFkYTI1ZmM5NDM4
11
+ NDUyODA3MmJjNTczNjZjOWNiZTA5M2Q3MTQ3NTc3ZDE5YmFkNTE=
12
12
  data.tar.gz: !binary |-
13
- MGQ2OWJlMmQzNTBkMWFjZTU1ODA2ODQyMmVlMzNiNTBiMDhiNjE3MGExNzU2
14
- NjhjYWRlN2EzMDFlMWExMTBjOTdmN2QxZjRmMGUwNTdmMzZmNmY0YmM0MTY5
15
- NjRkYzYyYzUwZTU5MTIxNGY5YWE4YmVkMzJjNWY1YzM0Nzc3OTY=
13
+ MzcyZmQ0MTE0MzlmOWYxZTI3NjU1NzkxZjZjNjA4Zjk3NjgxNjQ2NzgyZThk
14
+ YzBlMWI4NDM1YWQ0MjMxZWQ1ODBiMTA4ZGVhOGFmODkwYmUxZWUyZjAxZmMz
15
+ ZGU3ZDAxZTJiNTNlYzUwZDM1OTc4OWVhZDYyY2NkY2M1OTk3NGY=
@@ -2,9 +2,16 @@ require "redis_mutex/version"
2
2
  require 'securerandom'
3
3
 
4
4
  class RedisMutex
5
- SHAs = {}
5
+ SCRIPTS = {}
6
6
  MutexNotLockedError = Class.new(StandardError)
7
7
 
8
+ def self.def_redis_script(name, source)
9
+ SCRIPTS[name] = {
10
+ source: source,
11
+ sha: Digest::SHA1.hexdigest(source),
12
+ }
13
+ end
14
+
8
15
  def initialize(redis, name, token=nil)
9
16
  @redis = redis
10
17
  @name = name
@@ -22,40 +29,37 @@ class RedisMutex
22
29
  @redis.set(key, token, nx: true, ex: expire)
23
30
  end
24
31
 
25
- def release
26
- sha = SHAs[:delete_if_locked] ||= @redis.script(:load, <<-LUA)
27
- if ARGV[1] ~= redis.call('get', KEYS[1]) then
28
- return false
29
- end
30
-
31
- return redis.call('del', KEYS[1])
32
- LUA
32
+ def_redis_script :compare_and_delete, <<-LUA
33
+ if ARGV[1] ~= redis.call('get', KEYS[1]) then
34
+ return false
35
+ end
33
36
 
34
- @redis.evalsha(sha, [key], [token]) or raise MutexNotLockedError
37
+ return redis.call('del', KEYS[1])
38
+ LUA
39
+ def release
40
+ run_script(:compare_and_delete, [key], [token]) or raise MutexNotLockedError
35
41
  end
36
42
 
37
- def renew(expire)
38
- sha = SHAs[:set_expiration_if_locked] ||= @redis.script(:load, <<-LUA)
39
- if ARGV[1] ~= redis.call('get', KEYS[1]) then
40
- return false
41
- end
42
-
43
- return redis.call('expire', KEYS[1], ARGV[2])
44
- LUA
43
+ def_redis_script :compare_and_expire, <<-LUA
44
+ if ARGV[1] ~= redis.call('get', KEYS[1]) then
45
+ return false
46
+ end
45
47
 
46
- @redis.evalsha(sha, [key], [token, expire]) or raise MutexNotLockedError
48
+ return redis.call('expire', KEYS[1], ARGV[2])
49
+ LUA
50
+ def renew(expire)
51
+ run_script(:compare_and_expire, [key], [token, expire]) or raise MutexNotLockedError
47
52
  end
48
53
 
49
- def set_token(new_token)
50
- sha = SHAs[:compare_and_swap] ||= @redis.script(:load, <<-LUA)
51
- if ARGV[1] ~= redis.call('get', KEYS[1]) then
52
- return false
53
- end
54
-
55
- return redis.call('set', KEYS[1], ARGV[2])
56
- LUA
54
+ def_redis_script :compare_and_swap, <<-LUA
55
+ if ARGV[1] ~= redis.call('get', KEYS[1]) then
56
+ return false
57
+ end
57
58
 
58
- @redis.evalsha(sha, [key], [token, new_token]) or raise MutexNotLockedError
59
+ return redis.call('set', KEYS[1], ARGV[2])
60
+ LUA
61
+ def set_token(new_token)
62
+ run_script(:compare_and_swap, [key], [token, new_token]) or raise MutexNotLockedError
59
63
  @token = new_token
60
64
  end
61
65
 
@@ -66,4 +70,13 @@ class RedisMutex
66
70
  def verify!
67
71
  locked? or raise MutexNotLockedError
68
72
  end
73
+
74
+ private
75
+
76
+ def run_script(name, keys, args)
77
+ script = SCRIPTS.fetch(name)
78
+ @redis.evalsha(script.fetch(:sha), keys, args)
79
+ rescue Redis::CommandError
80
+ @redis.eval(script.fetch(:source), keys, args)
81
+ end
69
82
  end
@@ -117,4 +117,13 @@ class TestRedisMutex < Minitest::Test
117
117
  assert RedisMutex.new(redis, mutex_name, mutex_a.token).release
118
118
  end
119
119
 
120
+ def test_automatic_script_loading
121
+ # lock to ensure a script is loaded and its SHA cached
122
+ mutex_a.acquire_lock(1)
123
+ mutex_a.release
124
+
125
+ redis.script(:flush)
126
+ assert mutex_a.acquire_lock(1)
127
+ end
128
+
120
129
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis_mutex
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.pre.alpha.pre.10
4
+ version: 0.0.1.pre.alpha.pre.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Taylor Long