suo 0.3.2 → 0.3.3
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 +5 -5
- data/.travis.yml +4 -2
- data/CHANGELOG.md +5 -0
- data/README.md +9 -0
- data/lib/suo/client/base.rb +6 -11
- data/lib/suo/client/memcached.rb +8 -2
- data/lib/suo/client/redis.rb +8 -3
- data/lib/suo/version.rb +1 -1
- data/suo.gemspec +1 -2
- metadata +6 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 497f8d8c0021138da005c4ec8283a0f71d0b82120af2ffdf6bf0530c199c36b5
|
4
|
+
data.tar.gz: aae8820a1c19d314d1154960a7e09157b8094d89a13a9ae72d3842b332b7460f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c20da62ec8742cac1a622f54d841564921522ddda67cbc4cd2e9609aaa5440a392803e547bb4c19cab8243c70a244768935b0498e0bfdce2b59b92bb845c9079
|
7
|
+
data.tar.gz: de71d8bc43ad0396ec9d60ab76bc63836fcc75a8d0edb89a4b1de45d72dc0d2449ffd9a09cc3fe7b81d64ab7d3324e6f30df5f8dd1620f232d0886e28c9865ec
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
## 0.3.3
|
2
|
+
|
3
|
+
- Default TTL for keys to allow for short-lived locking keys (thanks to Ian Remillard) without leaking memory.
|
4
|
+
- Vastly improve initial lock acquisition, especially on Redis (thanks to Jeremy Wadscak).
|
5
|
+
|
1
6
|
## 0.3.2
|
2
7
|
|
3
8
|
- Custom lock tokens (thanks to avokhmin).
|
data/README.md
CHANGED
@@ -72,6 +72,15 @@ suo.lock do |token|
|
|
72
72
|
end
|
73
73
|
```
|
74
74
|
|
75
|
+
### Time To Live
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
Suo::Client::Redis.new("bar_resource", ttl: 60) #ttl in seconds
|
79
|
+
```
|
80
|
+
|
81
|
+
A key representing a set of lockable resources is removed once the last resource lock is released and the `ttl` time runs out. When another lock is acquired and the key has been removed the key has to be recreated.
|
82
|
+
|
83
|
+
|
75
84
|
## TODO
|
76
85
|
- more race condition tests
|
77
86
|
|
data/lib/suo/client/base.rb
CHANGED
@@ -5,7 +5,8 @@ module Suo
|
|
5
5
|
acquisition_timeout: 0.1,
|
6
6
|
acquisition_delay: 0.01,
|
7
7
|
stale_lock_expiration: 3600,
|
8
|
-
resources: 1
|
8
|
+
resources: 1,
|
9
|
+
ttl: 60,
|
9
10
|
}.freeze
|
10
11
|
|
11
12
|
BLANK_STR = "".freeze
|
@@ -55,16 +56,13 @@ module Suo
|
|
55
56
|
retry_with_timeout do
|
56
57
|
val, cas = get
|
57
58
|
|
58
|
-
if val.nil?
|
59
|
-
initial_set
|
60
|
-
next
|
61
|
-
end
|
59
|
+
cas = initial_set if val.nil?
|
62
60
|
|
63
61
|
cleared_locks = deserialize_and_clear_locks(val)
|
64
62
|
|
65
63
|
refresh_lock(cleared_locks, token)
|
66
64
|
|
67
|
-
break if set(serialize_locks(cleared_locks), cas)
|
65
|
+
break if set(serialize_locks(cleared_locks), cas, expire: cleared_locks.empty?)
|
68
66
|
end
|
69
67
|
end
|
70
68
|
|
@@ -81,7 +79,7 @@ module Suo
|
|
81
79
|
acquisition_lock = remove_lock(cleared_locks, token)
|
82
80
|
|
83
81
|
break unless acquisition_lock
|
84
|
-
break if set(serialize_locks(cleared_locks), cas)
|
82
|
+
break if set(serialize_locks(cleared_locks), cas, expire: cleared_locks.empty?)
|
85
83
|
end
|
86
84
|
rescue LockClientError => _ # rubocop:disable Lint/HandleExceptions
|
87
85
|
# ignore - assume success due to optimistic locking
|
@@ -101,10 +99,7 @@ module Suo
|
|
101
99
|
retry_with_timeout do
|
102
100
|
val, cas = get
|
103
101
|
|
104
|
-
if val.nil?
|
105
|
-
initial_set
|
106
|
-
next
|
107
|
-
end
|
102
|
+
cas = initial_set if val.nil?
|
108
103
|
|
109
104
|
cleared_locks = deserialize_and_clear_locks(val)
|
110
105
|
|
data/lib/suo/client/memcached.rb
CHANGED
@@ -16,12 +16,18 @@ module Suo
|
|
16
16
|
@client.get_cas(@key)
|
17
17
|
end
|
18
18
|
|
19
|
-
def set(newval, cas)
|
20
|
-
|
19
|
+
def set(newval, cas, expire: false)
|
20
|
+
if expire
|
21
|
+
@client.set_cas(@key, newval, cas, @options[:ttl])
|
22
|
+
else
|
23
|
+
@client.set_cas(@key, newval, cas)
|
24
|
+
end
|
21
25
|
end
|
22
26
|
|
23
27
|
def initial_set(val = BLANK_STR)
|
24
28
|
@client.set(@key, val)
|
29
|
+
_val, cas = @client.get_cas(@key)
|
30
|
+
cas
|
25
31
|
end
|
26
32
|
end
|
27
33
|
end
|
data/lib/suo/client/redis.rb
CHANGED
@@ -18,9 +18,13 @@ module Suo
|
|
18
18
|
[@client.get(@key), nil]
|
19
19
|
end
|
20
20
|
|
21
|
-
def set(newval, _)
|
21
|
+
def set(newval, _, expire: false)
|
22
22
|
ret = @client.multi do |multi|
|
23
|
-
|
23
|
+
if expire
|
24
|
+
multi.setex(@key, @options[:ttl], newval)
|
25
|
+
else
|
26
|
+
multi.set(@key, newval)
|
27
|
+
end
|
24
28
|
end
|
25
29
|
|
26
30
|
ret && ret[0] == OK_STR
|
@@ -35,7 +39,8 @@ module Suo
|
|
35
39
|
end
|
36
40
|
|
37
41
|
def initial_set(val = BLANK_STR)
|
38
|
-
|
42
|
+
set(val, nil)
|
43
|
+
nil
|
39
44
|
end
|
40
45
|
end
|
41
46
|
end
|
data/lib/suo/version.rb
CHANGED
data/suo.gemspec
CHANGED
@@ -16,7 +16,6 @@ Gem::Specification.new do |spec|
|
|
16
16
|
|
17
17
|
spec.files = `git ls-files -z`.split("\x0")
|
18
18
|
spec.bindir = "bin"
|
19
|
-
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
20
|
spec.require_paths = ["lib"]
|
22
21
|
|
@@ -28,7 +27,7 @@ Gem::Specification.new do |spec|
|
|
28
27
|
|
29
28
|
spec.add_development_dependency "bundler", "~> 1.5"
|
30
29
|
spec.add_development_dependency "rake", "~> 10.0"
|
31
|
-
spec.add_development_dependency "rubocop", "~> 0.
|
30
|
+
spec.add_development_dependency "rubocop", "~> 0.49.0"
|
32
31
|
spec.add_development_dependency "minitest", "~> 5.5.0"
|
33
32
|
spec.add_development_dependency "codeclimate-test-reporter", "~> 0.4.7"
|
34
33
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: suo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Elser
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-10-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dalli
|
@@ -86,14 +86,14 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 0.
|
89
|
+
version: 0.49.0
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: 0.
|
96
|
+
version: 0.49.0
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: minitest
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -125,9 +125,7 @@ dependencies:
|
|
125
125
|
description: Distributed locks (mutexes & semaphores) using Memcached or Redis.
|
126
126
|
email:
|
127
127
|
- nick.elser@gmail.com
|
128
|
-
executables:
|
129
|
-
- console
|
130
|
-
- setup
|
128
|
+
executables: []
|
131
129
|
extensions: []
|
132
130
|
extra_rdoc_files: []
|
133
131
|
files:
|
@@ -170,7 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
170
168
|
version: '0'
|
171
169
|
requirements: []
|
172
170
|
rubyforge_project:
|
173
|
-
rubygems_version: 2.
|
171
|
+
rubygems_version: 2.7.6
|
174
172
|
signing_key:
|
175
173
|
specification_version: 4
|
176
174
|
summary: Distributed locks (mutexes & semaphores) using Memcached or Redis.
|