zache 0.5.2 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 257081764cc35a64985d251872770a52136ad5bdab0a11c6183e61af038e2eed
4
- data.tar.gz: 8fcdeb45bdb0471b97b3706ad0c82b6779a11fc7d930b9e2d7706691f400acb1
3
+ metadata.gz: 60df3e71e2b231946894808553577fa3877e865f1556858d195e0d49957b75d0
4
+ data.tar.gz: 2d64c893d7bf7dd43d5788b9a3ad155df595dc8ad22b48f536ed4484b037dd4f
5
5
  SHA512:
6
- metadata.gz: 0a232c9be3072ade8f8d83c647f67b85d7506cc34a2c17bd3ce6b85af5cf0cd8c5aed420d0019264ad62c73855ec28bbe7443b170f006dede7eec3d5dfb077f5
7
- data.tar.gz: b0eb1264f9ad527ec8fa36f12b2911dfcdfb62c9add06c7de088401a546bb96836279692e7138a0e51e74c74b2f4e80b60a5e2d31007a1d9bf406463710abe91
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. You turn that off by using `sync` argument:
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
- @monitor = Monitor.new
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
- !@monitor.mon_try_enter { true }
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
- @monitor.synchronize do
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 test_sync_zache_is_reentrant
171
+ def test_sync_zache_is_not_reentrant
172
172
  cache = Zache.new
173
- cache.get(:first) { cache.get(:second) { cache.get(:third) { 1 } } }
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 test_fetches_multiple_keys_in_many_threads
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.2'
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.2
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-18 00:00:00.000000000 Z
11
+ date: 2018-12-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby