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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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