low_card_tables 1.0.0
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 +7 -0
- data/.gitignore +18 -0
- data/.travis.yml +59 -0
- data/Gemfile +17 -0
- data/LICENSE +21 -0
- data/README.md +75 -0
- data/Rakefile +6 -0
- data/lib/low_card_tables.rb +72 -0
- data/lib/low_card_tables/active_record/base.rb +55 -0
- data/lib/low_card_tables/active_record/migrations.rb +223 -0
- data/lib/low_card_tables/active_record/relation.rb +35 -0
- data/lib/low_card_tables/active_record/scoping.rb +87 -0
- data/lib/low_card_tables/errors.rb +74 -0
- data/lib/low_card_tables/has_low_card_table/base.rb +114 -0
- data/lib/low_card_tables/has_low_card_table/low_card_association.rb +273 -0
- data/lib/low_card_tables/has_low_card_table/low_card_associations_manager.rb +143 -0
- data/lib/low_card_tables/has_low_card_table/low_card_dynamic_method_manager.rb +224 -0
- data/lib/low_card_tables/has_low_card_table/low_card_objects_manager.rb +80 -0
- data/lib/low_card_tables/low_card_table/base.rb +184 -0
- data/lib/low_card_tables/low_card_table/cache.rb +214 -0
- data/lib/low_card_tables/low_card_table/cache_expiration/exponential_cache_expiration_policy.rb +151 -0
- data/lib/low_card_tables/low_card_table/cache_expiration/fixed_cache_expiration_policy.rb +23 -0
- data/lib/low_card_tables/low_card_table/cache_expiration/has_cache_expiration.rb +100 -0
- data/lib/low_card_tables/low_card_table/cache_expiration/no_caching_expiration_policy.rb +13 -0
- data/lib/low_card_tables/low_card_table/cache_expiration/unlimited_cache_expiration_policy.rb +13 -0
- data/lib/low_card_tables/low_card_table/row_collapser.rb +175 -0
- data/lib/low_card_tables/low_card_table/row_manager.rb +681 -0
- data/lib/low_card_tables/low_card_table/table_unique_index.rb +134 -0
- data/lib/low_card_tables/version.rb +4 -0
- data/lib/low_card_tables/version_support.rb +52 -0
- data/low_card_tables.gemspec +69 -0
- data/spec/low_card_tables/helpers/database_helper.rb +148 -0
- data/spec/low_card_tables/helpers/query_spy_helper.rb +47 -0
- data/spec/low_card_tables/helpers/system_helpers.rb +63 -0
- data/spec/low_card_tables/system/basic_system_spec.rb +254 -0
- data/spec/low_card_tables/system/bulk_system_spec.rb +334 -0
- data/spec/low_card_tables/system/caching_system_spec.rb +531 -0
- data/spec/low_card_tables/system/migrations_system_spec.rb +747 -0
- data/spec/low_card_tables/system/options_system_spec.rb +581 -0
- data/spec/low_card_tables/system/queries_system_spec.rb +142 -0
- data/spec/low_card_tables/system/validations_system_spec.rb +88 -0
- data/spec/low_card_tables/unit/active_record/base_spec.rb +53 -0
- data/spec/low_card_tables/unit/active_record/migrations_spec.rb +207 -0
- data/spec/low_card_tables/unit/active_record/relation_spec.rb +47 -0
- data/spec/low_card_tables/unit/active_record/scoping_spec.rb +101 -0
- data/spec/low_card_tables/unit/has_low_card_table/base_spec.rb +79 -0
- data/spec/low_card_tables/unit/has_low_card_table/low_card_association_spec.rb +287 -0
- data/spec/low_card_tables/unit/has_low_card_table/low_card_associations_manager_spec.rb +190 -0
- data/spec/low_card_tables/unit/has_low_card_table/low_card_dynamic_method_manager_spec.rb +234 -0
- data/spec/low_card_tables/unit/has_low_card_table/low_card_objects_manager_spec.rb +70 -0
- data/spec/low_card_tables/unit/low_card_table/base_spec.rb +207 -0
- data/spec/low_card_tables/unit/low_card_table/cache_expiration/exponential_cache_expiration_policy_spec.rb +128 -0
- data/spec/low_card_tables/unit/low_card_table/cache_expiration/fixed_cache_expiration_policy_spec.rb +25 -0
- data/spec/low_card_tables/unit/low_card_table/cache_expiration/has_cache_expiration_policy_spec.rb +100 -0
- data/spec/low_card_tables/unit/low_card_table/cache_expiration/no_caching_expiration_policy_spec.rb +14 -0
- data/spec/low_card_tables/unit/low_card_table/cache_expiration/unlimited_cache_expiration_policy_spec.rb +14 -0
- data/spec/low_card_tables/unit/low_card_table/cache_spec.rb +282 -0
- data/spec/low_card_tables/unit/low_card_table/row_collapser_spec.rb +109 -0
- data/spec/low_card_tables/unit/low_card_table/row_manager_spec.rb +918 -0
- data/spec/low_card_tables/unit/low_card_table/table_unique_index_spec.rb +117 -0
- metadata +206 -0
@@ -0,0 +1,531 @@
|
|
1
|
+
require 'low_card_tables'
|
2
|
+
require 'low_card_tables/helpers/database_helper'
|
3
|
+
require 'low_card_tables/helpers/system_helpers'
|
4
|
+
require 'low_card_tables/helpers/query_spy_helper'
|
5
|
+
|
6
|
+
describe "LowCardTables caching" do
|
7
|
+
include LowCardTables::Helpers::SystemHelpers
|
8
|
+
|
9
|
+
before :each do
|
10
|
+
@dh = LowCardTables::Helpers::DatabaseHelper.new
|
11
|
+
@dh.setup_activerecord!
|
12
|
+
|
13
|
+
create_standard_system_spec_tables!
|
14
|
+
create_standard_system_spec_models!
|
15
|
+
end
|
16
|
+
|
17
|
+
after :each do
|
18
|
+
drop_standard_system_spec_tables!
|
19
|
+
end
|
20
|
+
|
21
|
+
def create_basic_user(name = 'User1')
|
22
|
+
out = ::User.new
|
23
|
+
out.name = 'User1'
|
24
|
+
out.deleted = false
|
25
|
+
out.deceased = false
|
26
|
+
out.gender = 'female'
|
27
|
+
out.donation_level = 3
|
28
|
+
out.save!
|
29
|
+
|
30
|
+
out
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should have an explicit cache-flush call that works" do
|
34
|
+
LowCardTables::Helpers::QuerySpyHelper.with_query_spy("lctables_spec_user_statuses") do |spy|
|
35
|
+
create_basic_user("User1")
|
36
|
+
|
37
|
+
mid_count = spy.call_count
|
38
|
+
|
39
|
+
create_basic_user("User2")
|
40
|
+
|
41
|
+
spy.call_count.should == mid_count
|
42
|
+
|
43
|
+
::UserStatus.low_card_flush_cache!
|
44
|
+
create_basic_user("User3")
|
45
|
+
|
46
|
+
spy.call_count.should > mid_count
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should cache low-card rows in memory" do
|
51
|
+
LowCardTables::Helpers::QuerySpyHelper.with_query_spy("lctables_spec_user_statuses") do |spy|
|
52
|
+
spy.call_count.should == 0
|
53
|
+
|
54
|
+
user1 = create_basic_user
|
55
|
+
|
56
|
+
mid_calls = spy.call_count
|
57
|
+
mid_calls.should > 0
|
58
|
+
|
59
|
+
user2 = create_basic_user('User2')
|
60
|
+
|
61
|
+
spy.call_count.should == mid_calls
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should purge its cache efficiently when adding a new row" do
|
66
|
+
LowCardTables::Helpers::QuerySpyHelper.with_query_spy("lctables_spec_user_statuses") do |spy|
|
67
|
+
spy.call_count.should == 0
|
68
|
+
|
69
|
+
user1 = create_basic_user
|
70
|
+
|
71
|
+
mid_calls = spy.call_count
|
72
|
+
mid_calls.should > 0
|
73
|
+
|
74
|
+
user2 = ::User.new
|
75
|
+
user2.name = 'User2'
|
76
|
+
user2.deleted = false
|
77
|
+
user2.deceased = false
|
78
|
+
user2.gender = 'male'
|
79
|
+
user2.donation_level = 7
|
80
|
+
user2.save!
|
81
|
+
|
82
|
+
# We allow two calls here because we need it for our double-checked locking pattern.
|
83
|
+
(spy.call_count - mid_calls).should <= 2
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should handle the situation where a row in the database has a low-card ID that's not in cache" do
|
88
|
+
LowCardTables::Helpers::QuerySpyHelper.with_query_spy("lctables_spec_user_statuses") do |spy|
|
89
|
+
spy.call_count.should == 0
|
90
|
+
|
91
|
+
user1 = create_basic_user
|
92
|
+
|
93
|
+
mid_calls = spy.call_count
|
94
|
+
mid_calls.should > 0
|
95
|
+
|
96
|
+
new_status = ::UserStatusBackdoor.new
|
97
|
+
new_status.deleted = false
|
98
|
+
new_status.deceased = false
|
99
|
+
new_status.gender = 'male'
|
100
|
+
new_status.donation_level = 7
|
101
|
+
new_status.save!
|
102
|
+
|
103
|
+
old_status_id = user1.user_status_id
|
104
|
+
::User.where([ "id = :id", { :id => user1.id } ]).update_all([ "user_status_id = :new_status_id", { :new_status_id => new_status.id } ])
|
105
|
+
user1.user_status_id.should == old_status_id # make sure we didn't touch the existing object
|
106
|
+
|
107
|
+
# Make sure we didn't somehow invalidate the cache before this
|
108
|
+
spy.call_count.should == mid_calls
|
109
|
+
|
110
|
+
user2 = ::User.find(user1.id)
|
111
|
+
user2.deleted.should == false
|
112
|
+
user2.deceased.should == false
|
113
|
+
user2.gender.should == 'male'
|
114
|
+
user2.donation_level.should == 7
|
115
|
+
|
116
|
+
(spy.call_count - mid_calls).should > 0
|
117
|
+
(spy.call_count - mid_calls).should <= 2
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should be OK with manually-assigning an ID that's not in cache (that you somehow got out-of-band)" do
|
122
|
+
LowCardTables::Helpers::QuerySpyHelper.with_query_spy("lctables_spec_user_statuses") do |spy|
|
123
|
+
spy.call_count.should == 0
|
124
|
+
|
125
|
+
user1 = create_basic_user
|
126
|
+
|
127
|
+
mid_calls = spy.call_count
|
128
|
+
mid_calls.should > 0
|
129
|
+
|
130
|
+
new_status = ::UserStatusBackdoor.new
|
131
|
+
new_status.deleted = false
|
132
|
+
new_status.deceased = false
|
133
|
+
new_status.gender = 'male'
|
134
|
+
new_status.donation_level = 7
|
135
|
+
new_status.save!
|
136
|
+
|
137
|
+
user1.user_status_id = new_status.id
|
138
|
+
user1.deleted.should == false
|
139
|
+
user1.deceased.should == false
|
140
|
+
user1.gender.should == 'male'
|
141
|
+
user1.donation_level.should == 7
|
142
|
+
|
143
|
+
(spy.call_count - mid_calls).should > 0
|
144
|
+
(spy.call_count - mid_calls).should <= 2
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context "with a cache listener" do
|
149
|
+
before :each do
|
150
|
+
class CacheListener
|
151
|
+
def initialize
|
152
|
+
@calls = [ ]
|
153
|
+
end
|
154
|
+
|
155
|
+
def call(name, started, finished, unique_id, data)
|
156
|
+
@calls << { :name => name, :started => started, :finished => finished, :unique_id => unique_id, :data => data }
|
157
|
+
end
|
158
|
+
|
159
|
+
def listen!(*event_names)
|
160
|
+
event_names.each do |event_name|
|
161
|
+
ActiveSupport::Notifications.subscribe(event_name, self)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def unlisten!
|
166
|
+
ActiveSupport::Notifications.unsubscribe(self)
|
167
|
+
end
|
168
|
+
|
169
|
+
attr_reader :calls
|
170
|
+
end
|
171
|
+
|
172
|
+
@cache_listener = CacheListener.new
|
173
|
+
@cache_listener.listen!('low_card_tables.cache_load', 'low_card_tables.cache_flush', 'low_card_tables.rows_created')
|
174
|
+
end
|
175
|
+
|
176
|
+
after :each do
|
177
|
+
@cache_listener.unlisten!
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should notify listeners when flushing and loading its cache" do
|
181
|
+
@cache_listener.calls.length.should == 0
|
182
|
+
|
183
|
+
user1 = create_basic_user
|
184
|
+
|
185
|
+
call_count = @cache_listener.calls.length
|
186
|
+
call_count.should > 0
|
187
|
+
@cache_listener.calls.detect { |c| c[:name] == 'low_card_tables.cache_load' }.should be
|
188
|
+
|
189
|
+
start_time = Time.now
|
190
|
+
user1.deleted = true
|
191
|
+
user1.save!
|
192
|
+
end_time = Time.now
|
193
|
+
|
194
|
+
new_calls = @cache_listener.calls[call_count..-1]
|
195
|
+
new_calls.length.should > 0
|
196
|
+
|
197
|
+
flush_event = new_calls.detect { |c| c[:name] == 'low_card_tables.cache_flush' }
|
198
|
+
load_event = new_calls.detect { |c| c[:name] == 'low_card_tables.cache_load' }
|
199
|
+
flush_event.should be
|
200
|
+
load_event.should be
|
201
|
+
|
202
|
+
flush_event[:started].should >= start_time
|
203
|
+
flush_event[:finished].should >= flush_event[:started]
|
204
|
+
flush_event[:finished].should <= end_time
|
205
|
+
flush_event[:data][:reason].should == :creating_rows
|
206
|
+
flush_event[:data][:low_card_model].should == ::UserStatus
|
207
|
+
|
208
|
+
load_event[:started].should >= start_time
|
209
|
+
load_event[:started].should >= flush_event[:finished]
|
210
|
+
load_event[:finished].should >= load_event[:started]
|
211
|
+
load_event[:finished].should <= end_time
|
212
|
+
load_event[:data][:low_card_model].should == ::UserStatus
|
213
|
+
end
|
214
|
+
|
215
|
+
it "should notify listeners when the cache is manually flushed" do
|
216
|
+
user1 = create_basic_user
|
217
|
+
call_count = @cache_listener.calls.length
|
218
|
+
|
219
|
+
start_time = Time.now
|
220
|
+
::UserStatus.low_card_flush_cache!
|
221
|
+
new_calls = @cache_listener.calls[call_count..-1]
|
222
|
+
end_time = Time.now
|
223
|
+
|
224
|
+
new_calls.length.should == 1
|
225
|
+
new_call = new_calls[0]
|
226
|
+
new_call[:name].should == 'low_card_tables.cache_flush'
|
227
|
+
new_call[:started].should >= start_time
|
228
|
+
new_call[:finished].should >= new_call[:started]
|
229
|
+
new_call[:finished].should <= end_time
|
230
|
+
new_call[:data][:reason].should == :manually_requested
|
231
|
+
new_call[:data][:low_card_model].should == ::UserStatus
|
232
|
+
end
|
233
|
+
|
234
|
+
it "should notify listeners when the cache is flushed because an ID was not found" do
|
235
|
+
user1 = create_basic_user
|
236
|
+
call_count = @cache_listener.calls.length
|
237
|
+
|
238
|
+
start_time = Time.now
|
239
|
+
lambda do
|
240
|
+
::UserStatus.low_card_rows_for_ids([ user1.user_status_id, user1.user_status_id + 1000 ])
|
241
|
+
end.should raise_error(LowCardTables::Errors::LowCardIdNotFoundError)
|
242
|
+
|
243
|
+
new_calls = @cache_listener.calls[call_count..-1]
|
244
|
+
end_time = Time.now
|
245
|
+
|
246
|
+
new_calls.length.should > 1
|
247
|
+
new_call = new_calls.detect { |c| c[:name] == 'low_card_tables.cache_flush' && c[:data][:reason] == :id_not_found }
|
248
|
+
new_call[:name].should == 'low_card_tables.cache_flush'
|
249
|
+
new_call[:started].should >= start_time
|
250
|
+
new_call[:finished].should >= new_call[:started]
|
251
|
+
new_call[:finished].should <= end_time
|
252
|
+
new_call[:data][:reason].should == :id_not_found
|
253
|
+
new_call[:data][:low_card_model].should == ::UserStatus
|
254
|
+
end
|
255
|
+
|
256
|
+
it "should notify listeners when adding a new row" do
|
257
|
+
@cache_listener.calls.length.should == 0
|
258
|
+
|
259
|
+
user1 = create_basic_user
|
260
|
+
|
261
|
+
call_count = @cache_listener.calls.length
|
262
|
+
call_count.should > 0
|
263
|
+
|
264
|
+
start_time = Time.now
|
265
|
+
user1.gender = 'male'
|
266
|
+
user1.donation_level = 9
|
267
|
+
user1.save!
|
268
|
+
end_time = Time.now
|
269
|
+
|
270
|
+
new_calls = @cache_listener.calls[call_count..-1]
|
271
|
+
new_calls.length.should > 0
|
272
|
+
|
273
|
+
create_calls = new_calls.select { |c| c[:name] == 'low_card_tables.rows_created' }
|
274
|
+
create_calls.length.should == 1
|
275
|
+
create_call = create_calls[0]
|
276
|
+
|
277
|
+
create_call[:started].should >= start_time
|
278
|
+
create_call[:finished].should <= end_time
|
279
|
+
create_call[:finished].should >= create_call[:started]
|
280
|
+
create_call[:data][:low_card_model].should == ::UserStatus
|
281
|
+
|
282
|
+
keys = create_call[:data][:keys].map(&:to_s)
|
283
|
+
keys.sort.should == %w{deceased deleted donation_level gender}
|
284
|
+
|
285
|
+
values_array = create_call[:data][:values]
|
286
|
+
values_array.length.should == 1
|
287
|
+
values = values_array[0]
|
288
|
+
values.length.should == keys.length
|
289
|
+
|
290
|
+
values[keys.index('deceased')].should == false
|
291
|
+
values[keys.index('deleted')].should == false
|
292
|
+
values[keys.index('gender')].should == 'male'
|
293
|
+
values[keys.index('donation_level')].should == 9
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
context "cache policies" do
|
298
|
+
before :each do
|
299
|
+
class LowCardTables::LowCardTable::RowManager
|
300
|
+
def current_time
|
301
|
+
self.class.override_current_time || Time.now
|
302
|
+
end
|
303
|
+
|
304
|
+
class << self
|
305
|
+
def override_current_time=(x)
|
306
|
+
@override_current_time = x
|
307
|
+
end
|
308
|
+
|
309
|
+
def override_current_time
|
310
|
+
@override_current_time
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
module LowCardTables::LowCardTable::CacheExpiration::HasCacheExpiration::ClassMethods
|
316
|
+
def low_card_current_time
|
317
|
+
LowCardTables::LowCardTable::RowManager.override_current_time || Time.now
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
class LowCardTables::LowCardTable::Cache
|
322
|
+
def current_time
|
323
|
+
LowCardTables::LowCardTable::RowManager.override_current_time || Time.now
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
class LowCardTables::LowCardTable::CacheExpiration::ExponentialCacheExpirationPolicy
|
328
|
+
def current_time
|
329
|
+
LowCardTables::LowCardTable::RowManager.override_current_time || Time.now
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
def check_cache_expiration(*cache_expiration_settings, &block)
|
335
|
+
LowCardTables::Helpers::QuerySpyHelper.with_query_spy("lctables_spec_user_statuses") do |spy|
|
336
|
+
@start_time = Time.now
|
337
|
+
set_current_time(0)
|
338
|
+
|
339
|
+
::UserStatus.low_card_cache_expiration *cache_expiration_settings
|
340
|
+
|
341
|
+
user1 = create_basic_user
|
342
|
+
|
343
|
+
@last_call_count = spy.call_count
|
344
|
+
@spy = spy
|
345
|
+
|
346
|
+
block.call
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
def set_current_time(x)
|
351
|
+
LowCardTables::LowCardTable::RowManager.override_current_time = @start_time + x
|
352
|
+
end
|
353
|
+
|
354
|
+
def time_and_check(time, cached_or_not)
|
355
|
+
set_current_time(time)
|
356
|
+
new_user = create_basic_user
|
357
|
+
|
358
|
+
if cached_or_not == :cached
|
359
|
+
@spy.call_count.should == @last_call_count
|
360
|
+
elsif cached_or_not == :uncached
|
361
|
+
@spy.call_count.should > @last_call_count
|
362
|
+
@last_call_count = @spy.call_count
|
363
|
+
else
|
364
|
+
raise "Unknown cached_or_not: #{cached_or_not.inspect}"
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
it "should inherit policies correctly" do
|
369
|
+
::LowCardTables.low_card_cache_expiration 20
|
370
|
+
|
371
|
+
::LowCardTables.low_card_cache_expiration.should == 20
|
372
|
+
|
373
|
+
klass = Class.new(::ActiveRecord::Base)
|
374
|
+
klass.class_eval { is_low_card_table }
|
375
|
+
klass.low_card_cache_expiration.should == 20
|
376
|
+
|
377
|
+
::LowCardTables.low_card_cache_expiration :unlimited
|
378
|
+
klass.low_card_cache_expiration.should == :unlimited
|
379
|
+
|
380
|
+
klass.low_card_cache_expiration 40
|
381
|
+
klass.low_card_cache_expiration.should == 40
|
382
|
+
|
383
|
+
::LowCardTables.low_card_cache_expiration 190
|
384
|
+
klass.low_card_cache_expiration.should == 40
|
385
|
+
end
|
386
|
+
|
387
|
+
it "should apply a fixed setting correctly" do
|
388
|
+
check_cache_expiration(2.minutes) do |spy, initial_call_count|
|
389
|
+
time_and_check(119.seconds, :cached)
|
390
|
+
time_and_check(121.seconds, :uncached)
|
391
|
+
time_and_check(240.seconds, :cached)
|
392
|
+
time_and_check(242.seconds, :uncached)
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
it "should apply a setting of 0 correctly" do
|
397
|
+
check_cache_expiration(0) do |spy, initial_call_count|
|
398
|
+
time_and_check(1.seconds, :uncached)
|
399
|
+
time_and_check(1.seconds, :uncached)
|
400
|
+
time_and_check(2.seconds, :uncached)
|
401
|
+
time_and_check(3.seconds, :uncached)
|
402
|
+
time_and_check(3.seconds, :uncached)
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
it "should apply a setting of :unlimited correctly" do
|
407
|
+
check_cache_expiration(:unlimited) do |spy, initial_call_count|
|
408
|
+
time_and_check(1.seconds, :cached)
|
409
|
+
time_and_check(2.seconds, :cached)
|
410
|
+
time_and_check(5.years, :cached)
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
414
|
+
it "should apply a setting of :exponential with default settings correctly" do
|
415
|
+
check_cache_expiration(:exponential) do |spy, initial_call_count|
|
416
|
+
# 0-180: zero floor
|
417
|
+
time_and_check(0.seconds, :uncached)
|
418
|
+
time_and_check(1.seconds, :uncached)
|
419
|
+
time_and_check(30.seconds, :uncached)
|
420
|
+
time_and_check(90.seconds, :uncached)
|
421
|
+
time_and_check(179.seconds, :uncached)
|
422
|
+
|
423
|
+
# 180-190: ten second minimum
|
424
|
+
time_and_check(181.seconds, :uncached)
|
425
|
+
time_and_check(182.seconds, :cached)
|
426
|
+
time_and_check(189.seconds, :cached)
|
427
|
+
|
428
|
+
# 190-210: first doubling (20 seconds)
|
429
|
+
time_and_check(191.seconds, :uncached)
|
430
|
+
time_and_check(192.seconds, :cached)
|
431
|
+
time_and_check(209.seconds, :cached)
|
432
|
+
|
433
|
+
# 210-250: second doubling (40 seconds)
|
434
|
+
# don't check here -- want to make sure we skip this properly
|
435
|
+
|
436
|
+
# 250-330: third doubling (80 seconds)
|
437
|
+
time_and_check(251.seconds, :uncached)
|
438
|
+
time_and_check(295.seconds, :cached)
|
439
|
+
time_and_check(329.seconds, :cached)
|
440
|
+
|
441
|
+
# 330-490: fourth doubling (160 seconds)
|
442
|
+
# 490-810: fifth doubling (320 seconds)
|
443
|
+
# 810-1450: sixth doubling (640 seconds)
|
444
|
+
# 1450-2730: seventh doubling (1280 seconds)
|
445
|
+
# 2730-5290: eighth doubling (2560 seconds)
|
446
|
+
time_and_check(2731.seconds, :uncached)
|
447
|
+
time_and_check(2732.seconds, :cached)
|
448
|
+
time_and_check(5289.seconds, :cached)
|
449
|
+
|
450
|
+
# 5290-8890: max (3600 seconds)
|
451
|
+
time_and_check(5291.seconds, :uncached)
|
452
|
+
time_and_check(5292.seconds, :cached)
|
453
|
+
time_and_check(8889.seconds, :cached)
|
454
|
+
|
455
|
+
# 8890-12490: max (3600 seconds)
|
456
|
+
time_and_check(8891.seconds, :uncached)
|
457
|
+
time_and_check(8892.seconds, :cached)
|
458
|
+
time_and_check(12489.seconds, :cached)
|
459
|
+
|
460
|
+
# 12490-16090: max (3600 seconds)
|
461
|
+
time_and_check(12491.seconds, :uncached)
|
462
|
+
time_and_check(16089.seconds, :cached)
|
463
|
+
end
|
464
|
+
end
|
465
|
+
|
466
|
+
it "should apply a setting of :exponential with custom settings correctly" do
|
467
|
+
check_cache_expiration(:exponential, :zero_floor_time => 10.seconds, :min_time => 5.seconds, :exponent => 3.0, :max_time => 200.seconds) do |spy, initial_call_count|
|
468
|
+
# 0-10: zero floor
|
469
|
+
time_and_check(0.seconds, :uncached)
|
470
|
+
time_and_check(1.seconds, :uncached)
|
471
|
+
time_and_check(9.seconds, :uncached)
|
472
|
+
|
473
|
+
# 10-15: five second minimum
|
474
|
+
time_and_check(10.seconds, :uncached)
|
475
|
+
time_and_check(14.seconds, :cached)
|
476
|
+
|
477
|
+
# 15-30: first tripling (15 seconds)
|
478
|
+
time_and_check(16.seconds, :uncached)
|
479
|
+
time_and_check(17.seconds, :cached)
|
480
|
+
time_and_check(29.seconds, :cached)
|
481
|
+
|
482
|
+
# 30-75: second tripling (45 seconds)
|
483
|
+
time_and_check(31.seconds, :uncached)
|
484
|
+
time_and_check(32.seconds, :cached)
|
485
|
+
time_and_check(74.seconds, :cached)
|
486
|
+
|
487
|
+
# 75-210: third tripling (135 seconds)
|
488
|
+
|
489
|
+
# 210-410: max (200 seconds)
|
490
|
+
time_and_check(211.seconds, :uncached)
|
491
|
+
time_and_check(212.seconds, :cached)
|
492
|
+
time_and_check(409.seconds, :cached)
|
493
|
+
|
494
|
+
# 410-610: max (200 seconds)
|
495
|
+
time_and_check(411.seconds, :uncached)
|
496
|
+
time_and_check(412.seconds, :cached)
|
497
|
+
time_and_check(609.seconds, :cached)
|
498
|
+
end
|
499
|
+
end
|
500
|
+
|
501
|
+
it "should apply a setting of :exponential with custom settings with no zero floor" do
|
502
|
+
check_cache_expiration(:exponential, :zero_floor_time => 0, :min_time => 5.seconds, :exponent => 3.0, :max_time => 200.seconds) do |spy, initial_call_count|
|
503
|
+
# 0-5: five second minimum
|
504
|
+
time_and_check(1.seconds, :cached)
|
505
|
+
time_and_check(4.seconds, :cached)
|
506
|
+
|
507
|
+
# 5-20: first tripling (15 seconds)
|
508
|
+
time_and_check(6.seconds, :uncached)
|
509
|
+
time_and_check(7.seconds, :cached)
|
510
|
+
time_and_check(19.seconds, :cached)
|
511
|
+
|
512
|
+
# 20-65: second tripling (45 seconds)
|
513
|
+
time_and_check(21.seconds, :uncached)
|
514
|
+
time_and_check(22.seconds, :cached)
|
515
|
+
time_and_check(64.seconds, :cached)
|
516
|
+
|
517
|
+
# 65-200: third tripling (135 seconds)
|
518
|
+
|
519
|
+
# 200-400: max (200 seconds)
|
520
|
+
time_and_check(201.seconds, :uncached)
|
521
|
+
time_and_check(202.seconds, :cached)
|
522
|
+
time_and_check(399.seconds, :cached)
|
523
|
+
|
524
|
+
# 400-600: max (200 seconds)
|
525
|
+
time_and_check(401.seconds, :uncached)
|
526
|
+
time_and_check(402.seconds, :cached)
|
527
|
+
time_and_check(599.seconds, :cached)
|
528
|
+
end
|
529
|
+
end
|
530
|
+
end
|
531
|
+
end
|