atomic_cache 0.5.1.rc1 → 0.5.2.rc1

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: f03b8f8d9294f3a40ea719ea5165d4c6789c3eebb36459768c8fbd0c57d8fc3a
4
- data.tar.gz: b2a320b8323c57785e0202e29d89922b33e63fc9ebd898d6df61f76fb5e2600c
3
+ metadata.gz: 47216ee7b28e97d5a2a0d45ec7a7831d6ee05038f2029498654006b7ad42171c
4
+ data.tar.gz: 025c598a7d72bd3387c0fe0057a3047227ad9c6ae67ed818912a98d3a3f21e05
5
5
  SHA512:
6
- metadata.gz: f461c2bf7d903c6f7940334b8f5d11672c7ed04d1d55ad5d25c2337c07906d24a39f8958ddf04a2dd5d5dc690c9a0920121fb99c9f25c809c08959e48ee13ae3
7
- data.tar.gz: 9100ad9f5e5012c3729e3bc3a3b95ca64705c562f14e5d610df9f223436ee9351ec58cddc64b61c87c186a588f18e6158e891308aa5d431739f56aa2562744fa
6
+ metadata.gz: d575cb83f4bd7a97d902ad8b15d2da5063ea12edfcadc4d4b6c21f9ea1600413635cb84ee98025747bf49a82a7f97a91a73a5ba6152d7c5095ce19b556c5b7ad
7
+ data.tar.gz: 19486f04dfeb751f70b8e1c828b6affa6619829f2a467b87070b4c81a38d7656a57d7ceb02d935d1cf33e3bf4fc47f1356769cb27a19ae177a73cd0af86dbb6b
@@ -93,8 +93,8 @@ module AtomicCache
93
93
  end
94
94
 
95
95
  new_key = @timestamp_manager.next_key(keyspace, lmt)
96
- @timestamp_manager.promote(keyspace, last_known_key: new_key, timestamp: lmt)
97
96
  @storage.set(new_key, new_value, options)
97
+ @timestamp_manager.promote(keyspace, last_known_key: new_key, timestamp: lmt)
98
98
 
99
99
  metrics(:increment, 'generate.current-thread', tags: tags)
100
100
  log(:debug, "Generating new value for `#{new_key}`")
@@ -144,6 +144,16 @@ module AtomicCache
144
144
  if !value.nil?
145
145
  metrics(:increment, 'wait.present', tags: metrics_tags)
146
146
  return value
147
+ else
148
+ # if we didn't get a fresh value this go-round, check if there's a last known value
149
+ # if expirations were to come in rapidly, it's possible that the expiration which caused
150
+ # the wait cycle wrote a value, and it's now in LKV, and a new expiration came in, which
151
+ # has moved the LMT forward
152
+ value = last_known_value(keyspace, options, tags)
153
+ if !value.nil?
154
+ metrics(:increment, 'wait.lkv.present', tags: metrics_tags)
155
+ return value
156
+ end
147
157
  end
148
158
  end
149
159
 
@@ -44,8 +44,7 @@ module AtomicCache
44
44
  # @param last_known_key [String] a key with a known value to refer other processes to
45
45
  # @param timestamp [String, Numeric, Time] the timestamp with which the last_known_key was updated at
46
46
  def promote(keyspace, last_known_key:, timestamp:)
47
- key = keyspace.last_known_key_key
48
- @storage.set(key, last_known_key)
47
+ @storage.set(keyspace.last_known_key_key, last_known_key)
49
48
  @storage.set(last_modified_time_key, self.format(timestamp))
50
49
  end
51
50
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AtomicCache
4
- VERSION = "0.5.1.rc1"
4
+ VERSION = "0.5.2.rc1"
5
5
  end
@@ -163,6 +163,26 @@ describe 'AtomicCacheClient' do
163
163
  expect(result).to eq(new_value)
164
164
  end
165
165
 
166
+ it 'uses the last known value if the LMT increments while waiting' do
167
+ key_storage.set(timestamp_manager.last_modified_time_key, '1420090000')
168
+ key_storage.set(keyspace.last_known_key_key, 'lkk_key')
169
+ last_known_value = 'value from another thread'
170
+
171
+ # fetching the 'fresh' value continually returns nil (because LMT is incrementing forward)
172
+ allow(cache_storage).to receive(:read)
173
+ .with(timestamp_manager.current_key(keyspace), anything)
174
+ .and_return(nil, nil, nil, nil)
175
+
176
+ # multiple returned values are faking what it would look like if another process
177
+ # promoted a value (wrote LKV) but then the cache expired right after
178
+ allow(cache_storage).to receive(:read)
179
+ .with(timestamp_manager.last_known_key(keyspace), anything)
180
+ .and_return(nil, nil, nil, last_known_value)
181
+
182
+ result = subject.fetch(keyspace, backoff_duration_ms: 5) { 'value from generate' }
183
+ expect(result).to eq(last_known_value)
184
+ end
185
+
166
186
  it 'stops waiting when the max retry count is reached' do
167
187
  timestamp_manager.promote(keyspace, last_known_key: 'asdf', timestamp: 1420090000)
168
188
  result = subject.fetch(keyspace, backoff_duration_ms: 5) { 'value from generate' }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: atomic_cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1.rc1
4
+ version: 0.5.2.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ibotta Developers
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-07-12 00:00:00.000000000 Z
12
+ date: 2021-07-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler