zache 0.5.2 → 0.5.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 +4 -4
- data/README.md +9 -1
- data/lib/zache.rb +3 -5
- data/test/test_zache.rb +24 -3
- data/zache.gemspec +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 60df3e71e2b231946894808553577fa3877e865f1556858d195e0d49957b75d0
|
4
|
+
data.tar.gz: 2d64c893d7bf7dd43d5788b9a3ad155df595dc8ad22b48f536ed4484b037dd4f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27bb7605e2618a94c0bcc2d6978a19055bbced16b7f398a1ad232009d091259c7846efde96975bb0929940f9fc52a47345a62007b3b6fccaed7870eaf04cc267
|
7
|
+
data.tar.gz: 7101a0956069c62e85dfcc7796033e0133303a0f3b8ee87a46b90316991db1d2fd41ff1375c3b7fd1985412e7c301d9b876576d2f41b5876bc8550c3ad673441
|
data/README.md
CHANGED
@@ -25,13 +25,21 @@ zache = Zache.new
|
|
25
25
|
v = zache.get(:count, lifetime: 5 * 60) { expensive() }
|
26
26
|
```
|
27
27
|
|
28
|
-
By default `Zache` is thread-safe.
|
28
|
+
By default `Zache` is thread-safe. It locks the entire cache on each
|
29
|
+
`get` call. You turn that off by using `sync` argument:
|
29
30
|
|
30
31
|
```ruby
|
31
32
|
zache = Zache.new(sync: false)
|
32
33
|
v = zache.get(:count) { expensive() }
|
33
34
|
```
|
34
35
|
|
36
|
+
You may use "dirty" mode, which will return you an expired value, while
|
37
|
+
calculation is waiting. Say, you have something in the cache, but it's
|
38
|
+
expired. Then, you call `get` with a long running block. The thread waits,
|
39
|
+
while another one calls `get` again. That second thread won't wait, but will
|
40
|
+
receive what's left in the cache. This is a very convenient mode for situations
|
41
|
+
when you don't really care about data accuracy, but performance is an issue.
|
42
|
+
|
35
43
|
That's it.
|
36
44
|
|
37
45
|
# How to contribute
|
data/lib/zache.rb
CHANGED
@@ -22,8 +22,6 @@
|
|
22
22
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
23
23
|
# SOFTWARE.
|
24
24
|
|
25
|
-
require 'monitor'
|
26
|
-
|
27
25
|
# It is a very simple thread-safe in-memory cache with an ability to expire
|
28
26
|
# keys automatically, when their lifetime is over. Use it like this:
|
29
27
|
#
|
@@ -50,7 +48,7 @@ class Zache
|
|
50
48
|
@hash = {}
|
51
49
|
@sync = sync
|
52
50
|
@dirty = dirty
|
53
|
-
@
|
51
|
+
@mutex = Mutex.new
|
54
52
|
end
|
55
53
|
|
56
54
|
# Gets the value from the cache by the provided key. If the value is not
|
@@ -92,7 +90,7 @@ class Zache
|
|
92
90
|
|
93
91
|
# Is cache currently locked doing something?
|
94
92
|
def locked?
|
95
|
-
|
93
|
+
@mutex.locked?
|
96
94
|
end
|
97
95
|
|
98
96
|
# Put a value into the cache.
|
@@ -139,7 +137,7 @@ class Zache
|
|
139
137
|
|
140
138
|
def synchronized
|
141
139
|
if @sync
|
142
|
-
@
|
140
|
+
@mutex.synchronize do
|
143
141
|
# I don't know why, but if you remove this line, the tests will
|
144
142
|
# break. It seems to me that there is a bug in Ruby. Let's try to
|
145
143
|
# fix it or find a workaround and remove this line.
|
data/test/test_zache.rb
CHANGED
@@ -168,9 +168,11 @@ class ZacheTest < Minitest::Test
|
|
168
168
|
assert_equal(123, cache.get(:hey))
|
169
169
|
end
|
170
170
|
|
171
|
-
def
|
171
|
+
def test_sync_zache_is_not_reentrant
|
172
172
|
cache = Zache.new
|
173
|
-
|
173
|
+
assert_raises ThreadError do
|
174
|
+
cache.get(:first) { cache.get(:second) { 1 } }
|
175
|
+
end
|
174
176
|
end
|
175
177
|
|
176
178
|
def test_calculates_only_once
|
@@ -188,6 +190,15 @@ class ZacheTest < Minitest::Test
|
|
188
190
|
long.kill
|
189
191
|
end
|
190
192
|
|
193
|
+
def test_checks_locked_status_from_inside
|
194
|
+
cache = Zache.new
|
195
|
+
cache.get(:x) do
|
196
|
+
assert(cache.locked?)
|
197
|
+
'done'
|
198
|
+
end
|
199
|
+
assert(!cache.locked?)
|
200
|
+
end
|
201
|
+
|
191
202
|
def test_returns_dirty_result
|
192
203
|
cache = Zache.new
|
193
204
|
cache.get(:x, lifetime: 0) { 1 }
|
@@ -204,10 +215,20 @@ class ZacheTest < Minitest::Test
|
|
204
215
|
long.kill
|
205
216
|
end
|
206
217
|
|
207
|
-
def
|
218
|
+
def test_fetches_multiple_keys_in_many_threads_in_dirty_mode
|
208
219
|
cache = Zache.new(dirty: true)
|
209
220
|
set = Concurrent::Set.new
|
210
221
|
threads = 50
|
222
|
+
Threads.new(threads).assert(threads * 2) do |i|
|
223
|
+
set << cache.get(i, lifetime: 0.001) { i }
|
224
|
+
end
|
225
|
+
assert_equal(threads, set.size)
|
226
|
+
end
|
227
|
+
|
228
|
+
def test_fetches_multiple_keys_in_many_threads
|
229
|
+
cache = Zache.new
|
230
|
+
set = Concurrent::Set.new
|
231
|
+
threads = 50
|
211
232
|
Threads.new(threads).assert(threads * 2) do |i|
|
212
233
|
set << cache.get(i) { i }
|
213
234
|
end
|
data/zache.gemspec
CHANGED
@@ -31,7 +31,7 @@ Gem::Specification.new do |s|
|
|
31
31
|
s.rubygems_version = '2.5'
|
32
32
|
s.required_ruby_version = '>=2.5'
|
33
33
|
s.name = 'zache'
|
34
|
-
s.version = '0.5.
|
34
|
+
s.version = '0.5.3'
|
35
35
|
s.license = 'MIT'
|
36
36
|
s.summary = 'In-memory Cache'
|
37
37
|
s.description = 'Zero-footprint in-memory thread-safe cache'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-12-
|
11
|
+
date: 2018-12-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|