zache 0.4.0 → 0.5.0

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: 91965defa678c5b684064d7b868b46f7f8b31c9192209d6eb2f659055e790056
4
- data.tar.gz: 35d397d7fa7179e0968b564cad219a8e1aedaf0c2efc92e4fb7079faaec36d49
3
+ metadata.gz: a1b2d35db53d59daaf2d281eb08c0381bc0d7302cbab9d817c39b22e8aec93b0
4
+ data.tar.gz: db7d2212ceea4cc6f7e2f8feb5954b720c16ed0fd12fab56ea50c2d2fed5621c
5
5
  SHA512:
6
- metadata.gz: 88c5c68c7438dd4a34abc24a529815abb2020a4fc2502bab0d374fcc75e79b5bfb447c1f4b82d72cc7787c5bd0c0cb2aae8176da9a332b33bb8880ef3c286c4d
7
- data.tar.gz: 734f9721d3e726ba433881a325a724e4e2cfa45c5b94962753879d61dc33d9ed763ec1bb144b2042c87673746cfd753a7b7b708b7c83ff610777caa1b5ed8ffa
6
+ metadata.gz: 63ffba8c6c32c96aabbf443b6faa94bcbe4b8e5a6fb2f2a39ac36bdc6a68906c7d0f46a8266d10d485ed4ec463104d38f65bfed4cb3bf246a8d4cfdbe2da545e
7
+ data.tar.gz: 9b46a730a46d6a177092b1499f3cd020796eb4c63782a17cb0e8c54ad55e1fabbaf9b9d96ff703ab41e502e41dcf8d338a184e9fad4aae29eaddd95a19555938
data/.rubocop.yml CHANGED
@@ -13,3 +13,7 @@ Metrics/AbcSize:
13
13
  Max: 30
14
14
  Metrics/MethodLength:
15
15
  Max: 30
16
+ Metrics/CyclomaticComplexity:
17
+ Max: 10
18
+ Metrics/PerceivedComplexity:
19
+ Max: 10
data/lib/zache.rb CHANGED
@@ -43,9 +43,13 @@ class Zache
43
43
  # "sync" is whether the hash is thread-safe (`true`)
44
44
  # or not (`false`); it is recommended to leave this parameter untouched,
45
45
  # unless you really know what you are doing.
46
- def initialize(sync: true)
46
+ #
47
+ # If the <tt>dirty</tt> argument is set to <tt>true</tt>, a previously
48
+ # calculated result will be returned if it exists.
49
+ def initialize(sync: true, dirty: false)
47
50
  @hash = {}
48
51
  @sync = sync
52
+ @dirty = dirty
49
53
  @monitor = Monitor.new
50
54
  end
51
55
 
@@ -54,8 +58,14 @@ class Zache
54
58
  # the block is not given, an exception will be raised. The lifetime
55
59
  # must be in seconds. The default lifetime is huge, which means that the
56
60
  # key will never be expired.
57
- def get(key, lifetime: 2**32)
61
+ #
62
+ # If the <tt>dirty</tt> argument is set to <tt>true</tt>, a previously
63
+ # calculated result will be returned if it exists.
64
+ def get(key, lifetime: 2**32, dirty: false)
58
65
  if block_given?
66
+ if (dirty || @dirty) && locked? && !key_expired?(key) && @hash.key?(key)
67
+ return @hash[key]
68
+ end
59
69
  synchronized { calc(key, lifetime) { yield } }
60
70
  else
61
71
  rec = @hash[key]
@@ -80,6 +90,11 @@ class Zache
80
90
  !rec.nil?
81
91
  end
82
92
 
93
+ # Is cache currently locked doing something?
94
+ def locked?
95
+ !@monitor.mon_try_enter { true }
96
+ end
97
+
83
98
  # Put a value into the cache.
84
99
  def put(key, value, lifetime: 2**32)
85
100
  synchronized do
@@ -124,7 +139,7 @@ class Zache
124
139
 
125
140
  def synchronized
126
141
  if @sync
127
- @monitor.synchronize { yield }
142
+ @monitor.mon_synchronize { yield }
128
143
  else
129
144
  yield
130
145
  end
data/test/test_zache.rb CHANGED
@@ -24,6 +24,7 @@
24
24
 
25
25
  require 'minitest/autorun'
26
26
  require 'threads'
27
+ require 'timeout'
27
28
  require_relative '../lib/zache'
28
29
 
29
30
  # Cache test.
@@ -168,4 +169,32 @@ class ZacheTest < Minitest::Test
168
169
  cache = Zache.new
169
170
  cache.get(:first) { cache.get(:second) { cache.get(:third) { 1 } } }
170
171
  end
172
+
173
+ def test_calculates_only_once
174
+ cache = Zache.new
175
+ long = Thread.start do
176
+ cache.get(:x) do
177
+ sleep 0.5
178
+ 'first'
179
+ end
180
+ end
181
+ sleep 0.1
182
+ assert(cache.locked?)
183
+ cache.get(:x) { 'second' }
184
+ assert(!cache.locked?)
185
+ long.kill
186
+ end
187
+
188
+ def test_returns_dirty_result
189
+ cache = Zache.new
190
+ cache.get(:first, lifetime: 10) { 1 }
191
+ long = Thread.start do
192
+ cache.get(:first) { sleep 1000 }
193
+ end
194
+ sleep 0.1
195
+ Timeout.timeout(1) do
196
+ assert_equal(1, cache.get(:first, dirty: true) { 2 })
197
+ end
198
+ long.kill
199
+ end
171
200
  end
data/zache.gemspec CHANGED
@@ -31,7 +31,7 @@ Gem::Specification.new do |s|
31
31
  s.rubygems_version = '2.3.3'
32
32
  s.required_ruby_version = '>=2.3'
33
33
  s.name = 'zache'
34
- s.version = '0.4.0'
34
+ s.version = '0.5.0'
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.4.0
4
+ version: 0.5.0
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-01 00:00:00.000000000 Z
11
+ date: 2018-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest