suo 0.1.3 → 0.2.0
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 +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +16 -6
- data/lib/suo/client/base.rb +119 -137
- data/lib/suo/client/memcached.rb +12 -15
- data/lib/suo/client/redis.rb +21 -24
- data/lib/suo/version.rb +1 -1
- data/test/client_test.rb +58 -42
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 413b62af263af5a28c0fbf5691b30963f42f0883
|
4
|
+
data.tar.gz: 546c7fd3bac7b2222f6d9d2701a456c6a2aa6e36
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eca791c152ebf80a02307f7af951eb352b8891e1bf8ec75e674ca9db772c317df2bcdb63bc880f1c844a52f0246d0448aab6937bae9d914bf0c85c886714f61d
|
7
|
+
data.tar.gz: 721d0b259f9c87338227ec70e5d2a20b72672ab71d0402984c1e1afceb2dc71eaa3e274a50e1760ef4764220c0184a4994c0c37c6b4760579a346c91b55de6ab
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
## 0.2.0
|
2
|
+
|
3
|
+
- Refactor class methods into instance methods to simplify implementation.
|
4
|
+
- Increase thread safety with Memcached implementation.
|
5
|
+
|
1
6
|
## 0.1.3
|
2
7
|
|
3
8
|
- Properly throw Suo::LockClientError when the connection itself fails (Memcache server not reachable, etc.)
|
data/README.md
CHANGED
@@ -31,12 +31,22 @@ suo.lock("some_key") do
|
|
31
31
|
@puppies.pet!
|
32
32
|
end
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
34
|
+
Thread.new { suo.lock("other_key", 2) { puts "One"; sleep 2 } }
|
35
|
+
Thread.new { suo.lock("other_key", 2) { puts "Two"; sleep 2 } }
|
36
|
+
Thread.new { suo.lock("other_key", 2) { puts "Three" } }
|
37
|
+
|
38
|
+
# will print "One" "Two", but not "Three", as there are only 2 resources
|
39
|
+
|
40
|
+
# custom acquisition timeouts (time to acquire)
|
41
|
+
suo = Suo::Client::Memcached.new(client: some_dalli_client, acquisition_timeout: 1) # in seconds
|
42
|
+
|
43
|
+
# manually locking/unlocking
|
44
|
+
suo.lock("a_key")
|
45
|
+
foo.baz!
|
46
|
+
suo.unlock("a_key")
|
47
|
+
|
48
|
+
# custom stale lock cleanup (cleaning of dead clients)
|
49
|
+
suo = Suo::Client::Redis.new(client: some_redis_client, stale_lock_expiration: 60*5)
|
40
50
|
```
|
41
51
|
|
42
52
|
## TODO
|
data/lib/suo/client/base.rb
CHANGED
@@ -1,206 +1,188 @@
|
|
1
1
|
module Suo
|
2
2
|
module Client
|
3
3
|
class Base
|
4
|
-
|
5
4
|
DEFAULT_OPTIONS = {
|
6
|
-
|
7
|
-
|
5
|
+
acquisition_timeout: 0.1,
|
6
|
+
acquisition_delay: 0.01,
|
8
7
|
stale_lock_expiration: 3600
|
9
8
|
}.freeze
|
10
9
|
|
10
|
+
attr_accessor :client
|
11
|
+
|
12
|
+
include MonitorMixin
|
13
|
+
|
11
14
|
def initialize(options = {})
|
12
|
-
|
15
|
+
fail "Client required" unless options[:client]
|
16
|
+
@options = DEFAULT_OPTIONS.merge(options)
|
17
|
+
@retry_count = (@options[:acquisition_timeout] / @options[:acquisition_delay].to_f).ceil
|
18
|
+
@client = @options[:client]
|
19
|
+
super()
|
13
20
|
end
|
14
21
|
|
15
|
-
def lock(key, resources = 1
|
16
|
-
|
17
|
-
token = self.class.lock(key, resources, options)
|
22
|
+
def lock(key, resources = 1)
|
23
|
+
token = acquire_lock(key, resources)
|
18
24
|
|
19
|
-
if token
|
25
|
+
if block_given? && token
|
20
26
|
begin
|
21
|
-
yield
|
27
|
+
yield
|
22
28
|
ensure
|
23
|
-
|
29
|
+
unlock(key, token)
|
24
30
|
end
|
25
|
-
|
26
|
-
true
|
27
31
|
else
|
28
|
-
|
32
|
+
token
|
29
33
|
end
|
30
34
|
end
|
31
35
|
|
32
36
|
def locked?(key, resources = 1)
|
33
|
-
|
37
|
+
locks(key).size >= resources
|
34
38
|
end
|
35
39
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
acquisition_token = nil
|
40
|
-
token = SecureRandom.base64(16)
|
41
|
-
|
42
|
-
retry_with_timeout(key, options) do
|
43
|
-
val, cas = get(key, options)
|
44
|
-
|
45
|
-
if val.nil?
|
46
|
-
set_initial(key, options)
|
47
|
-
next
|
48
|
-
end
|
40
|
+
def locks(key)
|
41
|
+
val, _ = get(key)
|
42
|
+
locks = deserialize_locks(val)
|
49
43
|
|
50
|
-
|
51
|
-
|
52
|
-
if locks.size < resources
|
53
|
-
add_lock(locks, token)
|
44
|
+
locks
|
45
|
+
end
|
54
46
|
|
55
|
-
|
47
|
+
def refresh(key, acquisition_token)
|
48
|
+
retry_with_timeout(key) do
|
49
|
+
val, cas = get(key)
|
56
50
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
end
|
61
|
-
end
|
51
|
+
if val.nil?
|
52
|
+
set_initial(key)
|
53
|
+
next
|
62
54
|
end
|
63
55
|
|
64
|
-
|
65
|
-
end
|
66
|
-
|
67
|
-
def locked?(key, resources = 1, options = {})
|
68
|
-
locks(key, options).size >= resources
|
69
|
-
end
|
56
|
+
locks = deserialize_and_clear_locks(val)
|
70
57
|
|
71
|
-
|
72
|
-
options = merge_defaults(options)
|
73
|
-
val, _ = get(key, options)
|
74
|
-
locks = deserialize_locks(val)
|
58
|
+
refresh_lock(locks, acquisition_token)
|
75
59
|
|
76
|
-
locks
|
60
|
+
break if set(key, serialize_locks(locks), cas)
|
77
61
|
end
|
62
|
+
end
|
78
63
|
|
79
|
-
|
80
|
-
|
64
|
+
def unlock(key, acquisition_token)
|
65
|
+
return unless acquisition_token
|
81
66
|
|
82
|
-
|
83
|
-
|
67
|
+
retry_with_timeout(key) do
|
68
|
+
val, cas = get(key)
|
84
69
|
|
85
|
-
|
86
|
-
set_initial(key, options)
|
87
|
-
next
|
88
|
-
end
|
70
|
+
break if val.nil?
|
89
71
|
|
90
|
-
|
72
|
+
locks = deserialize_and_clear_locks(val)
|
91
73
|
|
92
|
-
|
74
|
+
acquisition_lock = remove_lock(locks, acquisition_token)
|
93
75
|
|
94
|
-
|
95
|
-
|
76
|
+
break unless acquisition_lock
|
77
|
+
break if set(key, serialize_locks(locks), cas)
|
96
78
|
end
|
79
|
+
rescue LockClientError => _ # rubocop:disable Lint/HandleExceptions
|
80
|
+
# ignore - assume success due to optimistic locking
|
81
|
+
end
|
97
82
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
return unless acquisition_token
|
102
|
-
|
103
|
-
retry_with_timeout(key, options) do
|
104
|
-
val, cas = get(key, options)
|
83
|
+
def clear(key) # rubocop:disable Lint/UnusedMethodArgument
|
84
|
+
fail NotImplementedError
|
85
|
+
end
|
105
86
|
|
106
|
-
|
87
|
+
private
|
107
88
|
|
108
|
-
|
89
|
+
def acquire_lock(key, resources = 1)
|
90
|
+
acquisition_token = nil
|
91
|
+
token = SecureRandom.base64(16)
|
109
92
|
|
110
|
-
|
93
|
+
retry_with_timeout(key) do
|
94
|
+
val, cas = get(key)
|
111
95
|
|
112
|
-
|
113
|
-
|
96
|
+
if val.nil?
|
97
|
+
set_initial(key)
|
98
|
+
next
|
114
99
|
end
|
115
|
-
rescue LockClientError => _ # rubocop:disable Lint/HandleExceptions
|
116
|
-
# ignore - assume success due to optimistic locking
|
117
|
-
end
|
118
|
-
|
119
|
-
def clear(key, options = {}) # rubocop:disable Lint/UnusedMethodArgument
|
120
|
-
fail NotImplementedError
|
121
|
-
end
|
122
100
|
|
123
|
-
|
124
|
-
options = self::DEFAULT_OPTIONS.merge(options)
|
101
|
+
locks = deserialize_and_clear_locks(val)
|
125
102
|
|
126
|
-
|
103
|
+
if locks.size < resources
|
104
|
+
add_lock(locks, token)
|
127
105
|
|
128
|
-
|
129
|
-
end
|
130
|
-
|
131
|
-
private
|
106
|
+
newval = serialize_locks(locks)
|
132
107
|
|
133
|
-
|
134
|
-
|
108
|
+
if set(key, newval, cas)
|
109
|
+
acquisition_token = token
|
110
|
+
break
|
111
|
+
end
|
112
|
+
end
|
135
113
|
end
|
136
114
|
|
137
|
-
|
138
|
-
|
139
|
-
end
|
115
|
+
acquisition_token
|
116
|
+
end
|
140
117
|
|
141
|
-
|
142
|
-
|
143
|
-
|
118
|
+
def get(key) # rubocop:disable Lint/UnusedMethodArgument
|
119
|
+
fail NotImplementedError
|
120
|
+
end
|
144
121
|
|
145
|
-
|
146
|
-
|
147
|
-
|
122
|
+
def set(key, newval, oldval) # rubocop:disable Lint/UnusedMethodArgument
|
123
|
+
fail NotImplementedError
|
124
|
+
end
|
148
125
|
|
149
|
-
|
150
|
-
|
126
|
+
def set_initial(key) # rubocop:disable Lint/UnusedMethodArgument
|
127
|
+
fail NotImplementedError
|
128
|
+
end
|
151
129
|
|
152
|
-
|
130
|
+
def synchronize(key) # rubocop:disable Lint/UnusedMethodArgument
|
131
|
+
mon_synchronize { yield }
|
132
|
+
end
|
153
133
|
|
154
|
-
|
155
|
-
|
156
|
-
break if now - start > options[:retry_timeout]
|
134
|
+
def retry_with_timeout(key)
|
135
|
+
start = Time.now.to_f
|
157
136
|
|
158
|
-
|
159
|
-
|
160
|
-
|
137
|
+
@retry_count.times do
|
138
|
+
now = Time.now.to_f
|
139
|
+
break if now - start > @options[:acquisition_timeout]
|
161
140
|
|
162
|
-
|
141
|
+
synchronize(key) do
|
142
|
+
yield
|
163
143
|
end
|
164
|
-
rescue => _
|
165
|
-
raise LockClientError
|
166
|
-
end
|
167
144
|
|
168
|
-
|
169
|
-
MessagePack.pack(locks.map { |time, token| [time.to_f, token] })
|
145
|
+
sleep(rand(@options[:acquisition_delay] * 1000).to_f / 1000)
|
170
146
|
end
|
147
|
+
rescue => _
|
148
|
+
raise LockClientError
|
149
|
+
end
|
171
150
|
|
172
|
-
|
173
|
-
|
174
|
-
|
151
|
+
def serialize_locks(locks)
|
152
|
+
MessagePack.pack(locks.map { |time, token| [time.to_f, token] })
|
153
|
+
end
|
175
154
|
|
176
|
-
|
177
|
-
|
155
|
+
def deserialize_and_clear_locks(val)
|
156
|
+
clear_expired_locks(deserialize_locks(val))
|
157
|
+
end
|
178
158
|
|
179
|
-
|
180
|
-
|
181
|
-
end
|
182
|
-
rescue EOFError => _
|
183
|
-
[]
|
184
|
-
end
|
159
|
+
def deserialize_locks(val)
|
160
|
+
unpacked = (val.nil? || val == "") ? [] : MessagePack.unpack(val)
|
185
161
|
|
186
|
-
|
187
|
-
|
188
|
-
locks.reject { |time, _| time < expired }
|
162
|
+
unpacked.map do |time, token|
|
163
|
+
[Time.at(time), token]
|
189
164
|
end
|
165
|
+
rescue EOFError => _
|
166
|
+
[]
|
167
|
+
end
|
190
168
|
|
191
|
-
|
192
|
-
|
193
|
-
|
169
|
+
def clear_expired_locks(locks)
|
170
|
+
expired = Time.now - @options[:stale_lock_expiration]
|
171
|
+
locks.reject { |time, _| time < expired }
|
172
|
+
end
|
194
173
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
end
|
174
|
+
def add_lock(locks, token)
|
175
|
+
locks << [Time.now.to_f, token]
|
176
|
+
end
|
199
177
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
178
|
+
def remove_lock(locks, acquisition_token)
|
179
|
+
lock = locks.find { |_, token| token == acquisition_token }
|
180
|
+
locks.delete(lock)
|
181
|
+
end
|
182
|
+
|
183
|
+
def refresh_lock(locks, acquisition_token)
|
184
|
+
remove_lock(locks, acquisition_token)
|
185
|
+
add_lock(locks, token)
|
204
186
|
end
|
205
187
|
end
|
206
188
|
end
|
data/lib/suo/client/memcached.rb
CHANGED
@@ -6,25 +6,22 @@ module Suo
|
|
6
6
|
super
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
options[:client].delete(key)
|
13
|
-
end
|
9
|
+
def clear(key)
|
10
|
+
@client.delete(key)
|
11
|
+
end
|
14
12
|
|
15
|
-
|
13
|
+
private
|
16
14
|
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
def get(key)
|
16
|
+
@client.get_cas(key)
|
17
|
+
end
|
20
18
|
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
def set(key, newval, cas)
|
20
|
+
@client.set_cas(key, newval, cas)
|
21
|
+
end
|
24
22
|
|
25
|
-
|
26
|
-
|
27
|
-
end
|
23
|
+
def set_initial(key)
|
24
|
+
@client.set(key, "")
|
28
25
|
end
|
29
26
|
end
|
30
27
|
end
|
data/lib/suo/client/redis.rb
CHANGED
@@ -6,37 +6,34 @@ module Suo
|
|
6
6
|
super
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
options[:client].del(key)
|
13
|
-
end
|
9
|
+
def clear(key)
|
10
|
+
@client.del(key)
|
11
|
+
end
|
14
12
|
|
15
|
-
|
13
|
+
private
|
16
14
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
def set(key, newval, _, options)
|
22
|
-
ret = options[:client].multi do |multi|
|
23
|
-
multi.set(key, newval)
|
24
|
-
end
|
15
|
+
def get(key)
|
16
|
+
[@client.get(key), nil]
|
17
|
+
end
|
25
18
|
|
26
|
-
|
19
|
+
def set(key, newval, _)
|
20
|
+
ret = @client.multi do |multi|
|
21
|
+
multi.set(key, newval)
|
27
22
|
end
|
28
23
|
|
29
|
-
|
30
|
-
|
31
|
-
yield
|
32
|
-
end
|
33
|
-
ensure
|
34
|
-
options[:client].unwatch
|
35
|
-
end
|
24
|
+
ret[0] == "OK"
|
25
|
+
end
|
36
26
|
|
37
|
-
|
38
|
-
|
27
|
+
def synchronize(key)
|
28
|
+
@client.watch(key) do
|
29
|
+
yield
|
39
30
|
end
|
31
|
+
ensure
|
32
|
+
@client.unwatch
|
33
|
+
end
|
34
|
+
|
35
|
+
def set_initial(key)
|
36
|
+
@client.set(key, "")
|
40
37
|
end
|
41
38
|
end
|
42
39
|
end
|
data/lib/suo/version.rb
CHANGED
data/test/client_test.rb
CHANGED
@@ -3,62 +3,55 @@ require "test_helper"
|
|
3
3
|
TEST_KEY = "suo_test_key".freeze
|
4
4
|
|
5
5
|
module ClientTests
|
6
|
-
def test_requires_client
|
7
|
-
exception = assert_raises(RuntimeError) do
|
8
|
-
@klass.lock(TEST_KEY, 1)
|
9
|
-
end
|
10
|
-
|
11
|
-
assert_equal "Client required", exception.message
|
12
|
-
end
|
13
|
-
|
14
6
|
def test_throws_failed_error_on_bad_client
|
15
7
|
assert_raises(Suo::LockClientError) do
|
16
|
-
@
|
8
|
+
client = @client.class.new(client: {})
|
9
|
+
client.lock(TEST_KEY, 1)
|
17
10
|
end
|
18
11
|
end
|
19
12
|
|
20
13
|
def test_class_single_resource_locking
|
21
|
-
lock1 = @
|
14
|
+
lock1 = @client.lock(TEST_KEY, 1)
|
22
15
|
refute_nil lock1
|
23
16
|
|
24
|
-
locked = @
|
17
|
+
locked = @client.locked?(TEST_KEY, 1)
|
25
18
|
assert_equal true, locked
|
26
19
|
|
27
|
-
lock2 = @
|
20
|
+
lock2 = @client.lock(TEST_KEY, 1)
|
28
21
|
assert_nil lock2
|
29
22
|
|
30
|
-
@
|
23
|
+
@client.unlock(TEST_KEY, lock1)
|
31
24
|
|
32
|
-
locked = @
|
25
|
+
locked = @client.locked?(TEST_KEY, 1)
|
33
26
|
|
34
27
|
assert_equal false, locked
|
35
28
|
end
|
36
29
|
|
37
30
|
def test_class_multiple_resource_locking
|
38
|
-
lock1 = @
|
31
|
+
lock1 = @client.lock(TEST_KEY, 2)
|
39
32
|
refute_nil lock1
|
40
33
|
|
41
|
-
locked = @
|
34
|
+
locked = @client.locked?(TEST_KEY, 2)
|
42
35
|
assert_equal false, locked
|
43
36
|
|
44
|
-
lock2 = @
|
37
|
+
lock2 = @client.lock(TEST_KEY, 2)
|
45
38
|
refute_nil lock2
|
46
39
|
|
47
|
-
locked = @
|
40
|
+
locked = @client.locked?(TEST_KEY, 2)
|
48
41
|
assert_equal true, locked
|
49
42
|
|
50
|
-
@
|
43
|
+
@client.unlock(TEST_KEY, lock1)
|
51
44
|
|
52
|
-
locked = @
|
45
|
+
locked = @client.locked?(TEST_KEY, 1)
|
53
46
|
assert_equal true, locked
|
54
47
|
|
55
|
-
@
|
48
|
+
@client.unlock(TEST_KEY, lock2)
|
56
49
|
|
57
|
-
locked = @
|
50
|
+
locked = @client.locked?(TEST_KEY, 1)
|
58
51
|
assert_equal false, locked
|
59
52
|
end
|
60
53
|
|
61
|
-
def
|
54
|
+
def test_block_single_resource_locking
|
62
55
|
locked = false
|
63
56
|
|
64
57
|
@client.lock(TEST_KEY, 1) { locked = true }
|
@@ -66,22 +59,45 @@ module ClientTests
|
|
66
59
|
assert_equal true, locked
|
67
60
|
end
|
68
61
|
|
69
|
-
def
|
62
|
+
def test_block_unlocks_on_exception
|
70
63
|
assert_raises(RuntimeError) do
|
71
64
|
@client.lock(TEST_KEY, 1) { fail "Test" }
|
72
65
|
end
|
73
66
|
|
74
|
-
locked = @
|
67
|
+
locked = @client.locked?(TEST_KEY, 1)
|
75
68
|
assert_equal false, locked
|
76
69
|
end
|
77
70
|
|
71
|
+
def test_readme_example
|
72
|
+
output = Queue.new
|
73
|
+
threads = []
|
74
|
+
|
75
|
+
threads << Thread.new { @client.lock(TEST_KEY, 2) { output << "One"; sleep 2 } }
|
76
|
+
threads << Thread.new { @client.lock(TEST_KEY, 2) { output << "Two"; sleep 2 } }
|
77
|
+
threads << Thread.new { @client.lock(TEST_KEY, 2) { output << "Three" } }
|
78
|
+
|
79
|
+
threads.map(&:join)
|
80
|
+
|
81
|
+
ret = []
|
82
|
+
|
83
|
+
ret << output.pop
|
84
|
+
ret << output.pop
|
85
|
+
|
86
|
+
ret.sort!
|
87
|
+
|
88
|
+
assert_equal 0, output.size
|
89
|
+
assert_equal ["One", "Two"], ret
|
90
|
+
end
|
91
|
+
|
78
92
|
def test_instance_multiple_resource_locking
|
79
93
|
success_counter = Queue.new
|
80
94
|
failure_counter = Queue.new
|
81
95
|
|
82
|
-
|
96
|
+
client = @client.class.new(acquisition_timeout: 0.9, client: @client.client)
|
97
|
+
|
98
|
+
100.times.map do |i|
|
83
99
|
Thread.new do
|
84
|
-
success = @client.lock(TEST_KEY,
|
100
|
+
success = @client.lock(TEST_KEY, 50) do
|
85
101
|
sleep(3)
|
86
102
|
success_counter << i
|
87
103
|
end
|
@@ -90,17 +106,19 @@ module ClientTests
|
|
90
106
|
end
|
91
107
|
end.map(&:join)
|
92
108
|
|
93
|
-
assert_equal
|
94
|
-
assert_equal
|
109
|
+
assert_equal 50, success_counter.size
|
110
|
+
assert_equal 50, failure_counter.size
|
95
111
|
end
|
96
112
|
|
97
113
|
def test_instance_multiple_resource_locking_longer_timeout
|
98
114
|
success_counter = Queue.new
|
99
115
|
failure_counter = Queue.new
|
100
116
|
|
101
|
-
|
117
|
+
client = @client.class.new(acquisition_timeout: 3, client: @client.client)
|
118
|
+
|
119
|
+
100.times.map do |i|
|
102
120
|
Thread.new do
|
103
|
-
success =
|
121
|
+
success = client.lock(TEST_KEY, 50) do
|
104
122
|
sleep(0.5)
|
105
123
|
success_counter << i
|
106
124
|
end
|
@@ -109,19 +127,19 @@ module ClientTests
|
|
109
127
|
end
|
110
128
|
end.map(&:join)
|
111
129
|
|
112
|
-
assert_equal
|
130
|
+
assert_equal 100, success_counter.size
|
113
131
|
assert_equal 0, failure_counter.size
|
114
132
|
end
|
115
133
|
end
|
116
134
|
|
117
135
|
class TestBaseClient < Minitest::Test
|
118
136
|
def setup
|
119
|
-
@
|
137
|
+
@client = Suo::Client::Base.new(client: {})
|
120
138
|
end
|
121
139
|
|
122
140
|
def test_not_implemented
|
123
141
|
assert_raises(NotImplementedError) do
|
124
|
-
@
|
142
|
+
@client.send(:get, TEST_KEY)
|
125
143
|
end
|
126
144
|
end
|
127
145
|
end
|
@@ -130,13 +148,12 @@ class TestMemcachedClient < Minitest::Test
|
|
130
148
|
include ClientTests
|
131
149
|
|
132
150
|
def setup
|
133
|
-
@
|
134
|
-
@client =
|
135
|
-
@klass_client = Dalli::Client.new("127.0.0.1:11211")
|
151
|
+
@dalli = Dalli::Client.new("127.0.0.1:11211")
|
152
|
+
@client = Suo::Client::Memcached.new
|
136
153
|
end
|
137
154
|
|
138
155
|
def teardown
|
139
|
-
@
|
156
|
+
@dalli.delete(TEST_KEY)
|
140
157
|
end
|
141
158
|
end
|
142
159
|
|
@@ -144,13 +161,12 @@ class TestRedisClient < Minitest::Test
|
|
144
161
|
include ClientTests
|
145
162
|
|
146
163
|
def setup
|
147
|
-
@
|
148
|
-
@client =
|
149
|
-
@klass_client = Redis.new
|
164
|
+
@redis = Redis.new
|
165
|
+
@client = Suo::Client::Redis.new
|
150
166
|
end
|
151
167
|
|
152
168
|
def teardown
|
153
|
-
@
|
169
|
+
@redis.del(TEST_KEY)
|
154
170
|
end
|
155
171
|
end
|
156
172
|
|