suo 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|