time_series 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +14 -0
- data/lib/key.rb +205 -0
- data/lib/redis_connection.rb +21 -0
- data/lib/time_series.rb +383 -0
- data/lib/version.rb +3 -0
- data/spec/compressor_spec.rb +311 -0
- data/spec/key_spec.rb +256 -0
- data/spec/time_series_spec.rb +125 -0
- data/time_series.gemspec +30 -0
- metadata +175 -0
data/lib/version.rb
ADDED
@@ -0,0 +1,311 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# http://mattsears.com/articles/2011/12/10/minitest-quick-reference
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'redis'
|
6
|
+
require_relative "../lib/time_series"
|
7
|
+
|
8
|
+
require "minitest/autorun"
|
9
|
+
require 'minitest/pride'
|
10
|
+
|
11
|
+
require 'active_support/core_ext/numeric/time.rb'
|
12
|
+
require 'active_support/core_ext/date/calculations.rb'
|
13
|
+
|
14
|
+
describe "TimeSeries" do
|
15
|
+
|
16
|
+
before do
|
17
|
+
$app_prefix="test"
|
18
|
+
@redis ||= Redis.new(:path => "/tmp/redis.sock")
|
19
|
+
@redis.keys("test:*").each{|k| @redis.del k}
|
20
|
+
end
|
21
|
+
|
22
|
+
after do
|
23
|
+
@redis.keys("test:*").each{|k| @redis.del k}
|
24
|
+
end
|
25
|
+
|
26
|
+
it "can separate older items from an array" do
|
27
|
+
ts = TimeSeries.new("test_ts")
|
28
|
+
array = Array.new
|
29
|
+
# create 7 days
|
30
|
+
(0..6).each do |i|
|
31
|
+
array << ts.time_to_key(Time.now - i.days)
|
32
|
+
end
|
33
|
+
|
34
|
+
ts.array_older_than(array, 3.days).must_be_instance_of Array
|
35
|
+
ts.array_older_than(array, 3.days).size.must_equal 4
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
it "can separate seconds, minutes,hours,... keys" do
|
40
|
+
ts = TimeSeries.new("test_ts")
|
41
|
+
|
42
|
+
# all methods must return empty arrays
|
43
|
+
ts.seconds.must_be_instance_of Array
|
44
|
+
ts.minutes.must_be_instance_of Array
|
45
|
+
ts.hours.must_be_instance_of Array
|
46
|
+
ts.days.must_be_instance_of Array
|
47
|
+
ts.months.must_be_instance_of Array
|
48
|
+
ts.years.must_be_instance_of Array
|
49
|
+
|
50
|
+
# all arrays are empty
|
51
|
+
ts.seconds.size.must_equal 0
|
52
|
+
ts.minutes.size.must_equal 0
|
53
|
+
ts.hours.size.must_equal 0
|
54
|
+
ts.days.size.must_equal 0
|
55
|
+
ts.months.size.must_equal 0
|
56
|
+
ts.years.size.must_equal 0
|
57
|
+
|
58
|
+
# seconds
|
59
|
+
@redis.zincrby "test:ts:test_ts:1986:12:30:23:59:01", 1, "one"
|
60
|
+
@redis.zincrby "test:ts:test_ts:1986:12:30:23:59:02", 1, "one"
|
61
|
+
@redis.zincrby "test:ts:test_ts:1986:12:30:23:59:03", 1, "one"
|
62
|
+
ts.seconds.size.must_equal 3
|
63
|
+
|
64
|
+
# minutes
|
65
|
+
@redis.zincrby "test:ts:test_ts:1986:12:30:23:59", 1, "one"
|
66
|
+
@redis.zincrby "test:ts:test_ts:1986:12:30:23:58", 1, "one"
|
67
|
+
@redis.zincrby "test:ts:test_ts:1986:12:30:23:57", 1, "one"
|
68
|
+
@redis.zincrby "test:ts:test_ts:1986:12:30:23:56", 1, "one"
|
69
|
+
ts.minutes.size.must_equal 4
|
70
|
+
|
71
|
+
# hours
|
72
|
+
@redis.zincrby "test:ts:test_ts:1986:12:30:23", 1, "one"
|
73
|
+
@redis.zincrby "test:ts:test_ts:1986:12:30:22", 1, "one"
|
74
|
+
@redis.zincrby "test:ts:test_ts:1986:12:30:21", 1, "one"
|
75
|
+
@redis.zincrby "test:ts:test_ts:1986:12:30:20", 1, "one"
|
76
|
+
@redis.zincrby "test:ts:test_ts:1986:12:30:19", 1, "one"
|
77
|
+
ts.hours.size.must_equal 5
|
78
|
+
|
79
|
+
# days
|
80
|
+
@redis.zincrby "test:ts:test_ts:1986:12:30", 1, "one"
|
81
|
+
@redis.zincrby "test:ts:test_ts:1986:12:29", 1, "one"
|
82
|
+
@redis.zincrby "test:ts:test_ts:1986:12:28", 1, "one"
|
83
|
+
@redis.zincrby "test:ts:test_ts:1986:12:27", 1, "one"
|
84
|
+
@redis.zincrby "test:ts:test_ts:1986:12:26", 1, "one"
|
85
|
+
@redis.zincrby "test:ts:test_ts:1986:12:25", 1, "one"
|
86
|
+
ts.days.size.must_equal 6
|
87
|
+
|
88
|
+
# months
|
89
|
+
@redis.zincrby "test:ts:test_ts:1986:12", 1, "one"
|
90
|
+
@redis.zincrby "test:ts:test_ts:1986:11", 1, "one"
|
91
|
+
@redis.zincrby "test:ts:test_ts:1986:10", 1, "one"
|
92
|
+
@redis.zincrby "test:ts:test_ts:1986:09", 1, "one"
|
93
|
+
@redis.zincrby "test:ts:test_ts:1986:08", 1, "one"
|
94
|
+
@redis.zincrby "test:ts:test_ts:1986:07", 1, "one"
|
95
|
+
@redis.zincrby "test:ts:test_ts:1986:06", 1, "one"
|
96
|
+
ts.months.size.must_equal 7
|
97
|
+
|
98
|
+
# years
|
99
|
+
@redis.zincrby "test:ts:test_ts:1986", 1, "one"
|
100
|
+
@redis.zincrby "test:ts:test_ts:1985", 1, "one"
|
101
|
+
@redis.zincrby "test:ts:test_ts:1984", 1, "one"
|
102
|
+
@redis.zincrby "test:ts:test_ts:1983", 1, "one"
|
103
|
+
@redis.zincrby "test:ts:test_ts:1982", 1, "one"
|
104
|
+
@redis.zincrby "test:ts:test_ts:1981", 1, "one"
|
105
|
+
@redis.zincrby "test:ts:test_ts:1980", 1, "one"
|
106
|
+
@redis.zincrby "test:ts:test_ts:1979", 1, "one"
|
107
|
+
ts.years.size.must_equal 8
|
108
|
+
|
109
|
+
# check everything is still as expected
|
110
|
+
ts.seconds.size.must_equal 3
|
111
|
+
ts.minutes.size.must_equal 4
|
112
|
+
ts.hours.size.must_equal 5
|
113
|
+
ts.days.size.must_equal 6
|
114
|
+
ts.months.size.must_equal 7
|
115
|
+
|
116
|
+
# make some keys volatile, volatile keys are not included
|
117
|
+
@redis.expire "test:ts:test_ts:1986:12:30:23:59:01", 10
|
118
|
+
@redis.expire "test:ts:test_ts:1986:12:30:23:59", 10
|
119
|
+
@redis.expire "test:ts:test_ts:1986:12:30:23", 10
|
120
|
+
@redis.expire "test:ts:test_ts:1986:12:30", 10
|
121
|
+
@redis.expire "test:ts:test_ts:1986:12", 10
|
122
|
+
@redis.expire "test:ts:test_ts:1986", 10
|
123
|
+
|
124
|
+
ts.seconds.size.must_equal 2
|
125
|
+
ts.minutes.size.must_equal 3
|
126
|
+
ts.hours.size.must_equal 4
|
127
|
+
ts.days.size.must_equal 5
|
128
|
+
ts.months.size.must_equal 6
|
129
|
+
ts.years.size.must_equal 7
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
it "can separate seconds, minutes,hours,... keys OLDER THAN" do
|
135
|
+
ts = TimeSeries.new("test_ts")
|
136
|
+
|
137
|
+
# create 7 seconds one day apart
|
138
|
+
(0..6).each do |i|
|
139
|
+
@redis.zincrby ts.time_to_key(Time.now - i.days), 1, "one"
|
140
|
+
end
|
141
|
+
ts.seconds(3.days).size.must_equal 4
|
142
|
+
|
143
|
+
# create 10 hours
|
144
|
+
(0..9).each do |i|
|
145
|
+
@redis.zincrby ts.time_to_key(Time.now - i.days).parent.parent, 1, "one"
|
146
|
+
end
|
147
|
+
ts.hours(1.hours).size.must_equal 9
|
148
|
+
|
149
|
+
# create 3 days
|
150
|
+
(0..2).each do |i|
|
151
|
+
@redis.zincrby ts.time_to_key(Time.now - i.days).parent.parent.parent, 1, "one"
|
152
|
+
end
|
153
|
+
ts.days(1.days).size.must_equal 2
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
it "can compress non recent seconds to minutes to hours" do
|
158
|
+
ts = TimeSeries.new("test_ts")
|
159
|
+
|
160
|
+
# create 10 seconds 30 seconds apart
|
161
|
+
(0..9).each do |i|
|
162
|
+
@redis.zincrby ts.time_to_key(Time.local(2000, 7, 31) - 30*i.seconds), 1, "one"
|
163
|
+
end
|
164
|
+
|
165
|
+
ts.keys.size.must_equal 10
|
166
|
+
ts.compress(ts.seconds).must_equal 10 # 10 seconds must be compressed
|
167
|
+
ts.keys.size.wont_equal 10
|
168
|
+
minutes_num = ts.keys.size
|
169
|
+
ts.keys.each { |k| k.minute?.must_equal true} # all keys must be minute keys
|
170
|
+
ts.compress(ts.minutes).must_equal minutes_num # all must be compressed
|
171
|
+
ts.keys.each { |k| k.hour?.must_equal true} # all keys must be hour keys
|
172
|
+
end
|
173
|
+
|
174
|
+
it "can compress non recent hours to days to months" do
|
175
|
+
ts = TimeSeries.new("test_ts")
|
176
|
+
# create 10 hours 6 hours apart
|
177
|
+
(0..9).each do |i|
|
178
|
+
@redis.zincrby ts.time_to_key(Time.local(2000, 7, 31) - 6*i.hours).parent.parent, 1, "one"
|
179
|
+
end
|
180
|
+
|
181
|
+
# create 10 minutes 6 hours apart on the year 2001
|
182
|
+
(0..9).each do |i|
|
183
|
+
@redis.zincrby ts.time_to_key(Time.local(2001, 7, 31) - 6*i.hours).parent, 1, "one"
|
184
|
+
end
|
185
|
+
|
186
|
+
ts.compress(ts.minutes).must_equal 10
|
187
|
+
ts.keys.each { |k| k.hour?.must_equal true} # all keys must be hour keys
|
188
|
+
ts.compress(ts.hours).must_equal 20
|
189
|
+
ts.keys.each { |k| k.day?.must_equal true} # all keys must be day keys
|
190
|
+
ts.compress ts.days
|
191
|
+
ts.keys.each { |k| k.month?.must_equal true} # all keys must be month keys
|
192
|
+
ts.compress ts.months
|
193
|
+
ts.keys.each { |k| k.year?.must_equal true} # all keys must be year keys
|
194
|
+
ts.keys.size.must_equal 2
|
195
|
+
end
|
196
|
+
|
197
|
+
it "can compress a mixture of minute, hour, day keys" do
|
198
|
+
ts = TimeSeries.new("test_ts")
|
199
|
+
|
200
|
+
# create 10 hours 6 hours apart
|
201
|
+
(0..9).each do |i|
|
202
|
+
@redis.zincrby ts.time_to_key(Time.local(2000, 7, 31) - 6*i.hours).parent.parent, 1, "one"
|
203
|
+
end
|
204
|
+
|
205
|
+
# create 10 minutes 6 hours apart on the year 2001
|
206
|
+
(0..9).each do |i|
|
207
|
+
@redis.zincrby ts.time_to_key(Time.local(2001, 7, 31) - 6*i.hours).parent, 1, "one"
|
208
|
+
end
|
209
|
+
|
210
|
+
# create 10 days 1 day apart on the year 2002
|
211
|
+
(0..9).each do |i|
|
212
|
+
@redis.zincrby ts.time_to_key(Time.local(2002, 7, 31) - i.days).parent.parent.parent, 1, "one"
|
213
|
+
end
|
214
|
+
|
215
|
+
ts.compress ts.keys
|
216
|
+
ts.compress ts.keys
|
217
|
+
ts.compress ts.keys
|
218
|
+
ts.compress ts.keys
|
219
|
+
ts.keys.each { |k| k.year?.must_equal true} # all keys must be year keys
|
220
|
+
ts.keys.size.must_equal 3
|
221
|
+
|
222
|
+
end
|
223
|
+
|
224
|
+
it "can compress a mixture of keys but will exclude recent keys" do
|
225
|
+
ts = TimeSeries.new("test_ts")
|
226
|
+
|
227
|
+
max_hour = Time.now.hour
|
228
|
+
max_min = Time.now.min
|
229
|
+
max_sec = Time.now.sec
|
230
|
+
max_day = Time.now.day
|
231
|
+
|
232
|
+
# create seconds
|
233
|
+
(1..max_sec).each do |i|
|
234
|
+
@redis.zincrby ts.time_to_key(Time.now - i), 1, "one"
|
235
|
+
end
|
236
|
+
|
237
|
+
# create hours
|
238
|
+
(1...max_hour).each do |i|
|
239
|
+
@redis.zincrby ts.time_to_key(Time.now - i.hours).parent.parent, 1, "one"
|
240
|
+
end
|
241
|
+
|
242
|
+
# create minutes
|
243
|
+
(1..max_min).each do |i|
|
244
|
+
@redis.zincrby ts.time_to_key(Time.now - i.minutes).parent, 1, "one"
|
245
|
+
end
|
246
|
+
|
247
|
+
# create days
|
248
|
+
(1...max_day).each do |i|
|
249
|
+
@redis.zincrby ts.time_to_key(Time.now - i.days).parent.parent.parent, 1, "one"
|
250
|
+
end
|
251
|
+
|
252
|
+
# create months
|
253
|
+
(1...max_day).each do |i|
|
254
|
+
@redis.zincrby ts.time_to_key(Time.now - i.days).parent.parent.parent, 1, "one"
|
255
|
+
end
|
256
|
+
|
257
|
+
recent_keys = ts.keys
|
258
|
+
ts.compress ts.keys
|
259
|
+
ts.compress ts.keys
|
260
|
+
ts.compress ts.keys
|
261
|
+
ts.compress ts.keys
|
262
|
+
ts.keys.must_equal recent_keys # nothing must be compressed
|
263
|
+
|
264
|
+
# Now create a mixture of non recent keys
|
265
|
+
|
266
|
+
# create non recent hours
|
267
|
+
(1...max_hour).each do |i|
|
268
|
+
@redis.zincrby ts.time_to_key(Time.local(2002, 7, 31) - i.hours).parent.parent, 1, "one"
|
269
|
+
end
|
270
|
+
|
271
|
+
all_keys = ts.keys
|
272
|
+
ts.compress ts.keys
|
273
|
+
ts.compress ts.keys
|
274
|
+
ts.compress ts.keys
|
275
|
+
ts.compress ts.keys
|
276
|
+
ts.keys.wont_equal all_keys # something must be compressed
|
277
|
+
"test:ts:test_ts:2002".exists?.must_equal true
|
278
|
+
end
|
279
|
+
|
280
|
+
it "remove terms by score" do
|
281
|
+
ts = TimeSeries.new("test_ts")
|
282
|
+
|
283
|
+
@redis.zincrby "test:ts:test_ts:1986", 1, "one"
|
284
|
+
@redis.zincrby "test:ts:test_ts:1986", 2, "two"
|
285
|
+
@redis.zincrby "test:ts:test_ts:1986", 3, "three"
|
286
|
+
@redis.zincrby "test:ts:test_ts:1986", 4, "four"
|
287
|
+
@redis.zincrby "test:ts:test_ts:1986", 5, "five"
|
288
|
+
@redis.zincrby "test:ts:test_ts:1986", 6, "six"
|
289
|
+
|
290
|
+
@redis.zincrby "test:ts:test_ts:1987", 1, "one"
|
291
|
+
@redis.zincrby "test:ts:test_ts:1987", 2, "two"
|
292
|
+
@redis.zincrby "test:ts:test_ts:1987", 3, "three"
|
293
|
+
@redis.zincrby "test:ts:test_ts:1987", 4, "four"
|
294
|
+
@redis.zincrby "test:ts:test_ts:1987", 5, "five"
|
295
|
+
@redis.zincrby "test:ts:test_ts:1987", 6, "six"
|
296
|
+
|
297
|
+
@redis.zincrby "test:ts:test_ts:1988:01", 1, "one"
|
298
|
+
@redis.zincrby "test:ts:test_ts:1988:01", 2, "two"
|
299
|
+
@redis.zincrby "test:ts:test_ts:1988:01", 3, "three"
|
300
|
+
@redis.zincrby "test:ts:test_ts:1988:01", 4, "four"
|
301
|
+
@redis.zincrby "test:ts:test_ts:1988:01", 5, "five"
|
302
|
+
@redis.zincrby "test:ts:test_ts:1988:01", 6, "six"
|
303
|
+
|
304
|
+
ts.remove_by_score ts.keys, 4
|
305
|
+
|
306
|
+
expected = { "five" => 5, "six" => 6 }
|
307
|
+
"test:ts:test_ts:1986".get.must_equal expected
|
308
|
+
"test:ts:test_ts:1987".get.must_equal expected
|
309
|
+
"test:ts:test_ts:1988:01".get.must_equal expected
|
310
|
+
end
|
311
|
+
end
|
data/spec/key_spec.rb
ADDED
@@ -0,0 +1,256 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# http://mattsears.com/articles/2011/12/10/minitest-quick-reference
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'redis'
|
6
|
+
require "minitest/autorun"
|
7
|
+
require 'minitest/pride'
|
8
|
+
require_relative '../lib/key'
|
9
|
+
|
10
|
+
describe "Key String" do
|
11
|
+
|
12
|
+
before do
|
13
|
+
$app_prefix="test"
|
14
|
+
@redis ||= Redis.new(:path => "/tmp/redis.sock")
|
15
|
+
@redis.keys("test:*").each{|k| @redis.del k}
|
16
|
+
end
|
17
|
+
|
18
|
+
after do
|
19
|
+
@redis.keys("test:*").each{|k| @redis.del k}
|
20
|
+
end
|
21
|
+
|
22
|
+
it "exists?" do
|
23
|
+
key = "test:ts:test_ts:2012:11:10:09:08"
|
24
|
+
key.exists?.must_equal false
|
25
|
+
@redis.zincrby key, 2, "one"
|
26
|
+
key.exists?.must_equal true
|
27
|
+
end
|
28
|
+
|
29
|
+
it "determines its prefix" do
|
30
|
+
key = "test:ts:test_ts:2012:11:10:09:08"
|
31
|
+
key.prefix.must_equal "test:ts:test_ts:"
|
32
|
+
end
|
33
|
+
|
34
|
+
it "has_children" do
|
35
|
+
key = "test:ts:test_ts:1986:11:04:12:05"
|
36
|
+
@redis.zincrby "test:ts:test_ts:1986:11:04:12:05:01", 2, "one"
|
37
|
+
key.has_children?.must_equal true
|
38
|
+
end
|
39
|
+
|
40
|
+
it "can determine volatile? / persistant? keys" do
|
41
|
+
key = "test:ts:test_ts:1986:11:04:12:05"
|
42
|
+
@redis.zincrby key, 2, "one"
|
43
|
+
key.persistant?.must_equal true
|
44
|
+
key.volatile?.must_equal false
|
45
|
+
|
46
|
+
@redis.expire key, 10
|
47
|
+
key.persistant?.must_equal false
|
48
|
+
key.volatile?.must_equal true
|
49
|
+
|
50
|
+
"non_existant_key".persistant?.must_equal false
|
51
|
+
"non_existant_key".volatile?.must_equal false
|
52
|
+
end
|
53
|
+
|
54
|
+
it "has parent" do
|
55
|
+
key = "test:ts:test_ts:1986:11:04:12:05"
|
56
|
+
@redis.zincrby "test:ts:test_ts:1986:11:04:12", 2, "one"
|
57
|
+
key.has_parent?.must_equal true
|
58
|
+
end
|
59
|
+
|
60
|
+
it "has non persistant parent" do
|
61
|
+
key = "test:ts:test_ts:1986:11:04:12:05" #second resolution
|
62
|
+
|
63
|
+
@redis.zincrby "test:ts:test_ts:1986:11:04:12", 2, "one" #create parent
|
64
|
+
key.has_persistant_parent?.must_equal true
|
65
|
+
@redis.expire "test:ts:test_ts:1986:11:04:12" , 10 #make parent volatile
|
66
|
+
key.has_persistant_parent?.must_equal false
|
67
|
+
|
68
|
+
"test:ts:test_ts:1986:11:04:12".has_persistant_parent?.must_equal false #key exists, parent no
|
69
|
+
"test:ts:test_ts:1986:11".has_persistant_parent?.must_equal false #key and parent do not exist
|
70
|
+
end
|
71
|
+
|
72
|
+
it "has volative parent" do
|
73
|
+
key = "test:ts:test_ts:1986:11:04:12:05"
|
74
|
+
@redis.zincrby "test:ts:test_ts:1986:11:04:12", 2, "one"
|
75
|
+
@redis.expire "test:ts:test_ts:1986:11:04:12", 2
|
76
|
+
key.has_volatile_parent?.must_equal true
|
77
|
+
end
|
78
|
+
|
79
|
+
it "has children" do
|
80
|
+
key = "test:ts:test_ts:1986:11:04:12:05"
|
81
|
+
@redis.zincrby "test:ts:test_ts:1986:11:04:12:05:01", 2, "one"
|
82
|
+
@redis.zincrby "test:ts:test_ts:1986:11:04:12:05:02", 2, "one"
|
83
|
+
@redis.zincrby "test:ts:test_ts:1986:11:04:12:05:03:00", 2, "one"
|
84
|
+
@redis.zincrby "test:ts:test_ts:1986:11:04:12:06:01", 2, "one" # non children
|
85
|
+
key.children.size.must_equal 3
|
86
|
+
end
|
87
|
+
|
88
|
+
it "can separate persistant children" do
|
89
|
+
key = "test:ts:test_ts:1986:11:04:12:05"
|
90
|
+
@redis.zincrby "test:ts:test_ts:1986:11:04:12:05:01", 2, "one"
|
91
|
+
@redis.zincrby "test:ts:test_ts:1986:11:04:12:05:02", 2, "one"
|
92
|
+
@redis.zincrby "test:ts:test_ts:1986:11:04:12:05:05", 2, "one"
|
93
|
+
@redis.zincrby "test:ts:test_ts:1986:11:04:12:05:06", 2, "one"
|
94
|
+
@redis.zincrby "test:ts:test_ts:1986:11:04:12:05:07", 2, "one"
|
95
|
+
@redis.zincrby "test:ts:test_ts:1986:11:04:12:05:08", 2, "one"
|
96
|
+
@redis.zincrby "test:ts:test_ts:1986:11:04:12:05:09", 2, "one"
|
97
|
+
@redis.zincrby "test:ts:test_ts:1986:11:04:12:05:10", 2, "one"
|
98
|
+
@redis.zincrby "test:ts:test_ts:1986:11:04:12:05:03:00", 2, "one"
|
99
|
+
|
100
|
+
@redis.expire "test:ts:test_ts:1986:11:04:12:05:01", 5
|
101
|
+
@redis.expire "test:ts:test_ts:1986:11:04:12:05:06", 5
|
102
|
+
@redis.expire "test:ts:test_ts:1986:11:04:12:05:08", 5
|
103
|
+
@redis.expire "test:ts:test_ts:1986:11:04:12:05:03:00", 5
|
104
|
+
|
105
|
+
@redis.zincrby "test:ts:test_ts:1986:11:04:12:06:01", 2, "one" # hobo
|
106
|
+
@redis.zincrby "test:ts:test_ts:1986:11:04:12:07", 2, "one" # hobo
|
107
|
+
|
108
|
+
key.children.size.must_equal 9
|
109
|
+
key.persistant_children.size.must_equal 5
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
it "has siblings" do
|
114
|
+
key = "test:ts:test_ts:1986:11"
|
115
|
+
@redis.zincrby "test:ts:test_ts:1986:12", 2, "one"
|
116
|
+
@redis.zincrby "test:ts:test_ts:1986:13", 2, "one"
|
117
|
+
@redis.zincrby "test:ts:test_ts:1986:14", 2, "one"
|
118
|
+
@redis.zincrby "test:ts:test_ts:1986:15", 2, "one"
|
119
|
+
@redis.zincrby "test:ts:test_ts:1987:15", 2, "one" # non sibling
|
120
|
+
key.siblings_keys.size.must_equal 4
|
121
|
+
end
|
122
|
+
|
123
|
+
it "can unionize persistant children children" do
|
124
|
+
key = "test:ts:test_ts:1986:01"
|
125
|
+
@redis.zincrby "test:ts:test_ts:1986:01:10", 1, "one"
|
126
|
+
@redis.zincrby "test:ts:test_ts:1986:01:11", 1, "one"
|
127
|
+
@redis.zincrby "test:ts:test_ts:1986:01:12", 1, "one"
|
128
|
+
@redis.zincrby "test:ts:test_ts:1986:01:13", 1, "one"
|
129
|
+
@redis.zincrby "test:ts:test_ts:1986:01:14:01", 1, "one"
|
130
|
+
@redis.zincrby "test:ts:test_ts:1986:01:14:02", 1, "one"
|
131
|
+
@redis.zincrby "test:ts:test_ts:1986:01:10", 2, "two"
|
132
|
+
@redis.zincrby "test:ts:test_ts:1986:01:11", 2, "two"
|
133
|
+
@redis.zincrby "test:ts:test_ts:1986:01:12", 2, "two"
|
134
|
+
@redis.zincrby "test:ts:test_ts:1986:01:13", 2, "two"
|
135
|
+
@redis.zincrby "test:ts:test_ts:1986:01:14:01", 2, "two"
|
136
|
+
@redis.zincrby "test:ts:test_ts:1986:01:14:02", 2, "two"
|
137
|
+
key.unionize_persistant_children
|
138
|
+
key.exists?.must_equal true
|
139
|
+
key.volatile?.must_equal true
|
140
|
+
end
|
141
|
+
|
142
|
+
it "detects its resolution" do
|
143
|
+
"test:ts:test_ts:1986".resolution.must_equal :year
|
144
|
+
"test:ts:test_ts:1986:01".resolution.must_equal :month
|
145
|
+
"test:ts:test_ts:1986:01:14".resolution.must_equal :day
|
146
|
+
"test:ts:test_ts:1986:01:14:02".resolution.must_equal :hour
|
147
|
+
"test:ts:test_ts:1986:01:14:02:58".resolution.must_equal :minute
|
148
|
+
"test:ts:test_ts:1986:01:14:02:10:11".resolution.must_equal :second
|
149
|
+
end
|
150
|
+
|
151
|
+
it "detects year, month, ..." do
|
152
|
+
"test:ts:test_ts:1986".year.must_equal 1986
|
153
|
+
"test:ts:test_ts:1986:01".month.must_equal 1
|
154
|
+
"test:ts:test_ts:1986:08:02".day.must_equal 2
|
155
|
+
"test:ts:test_ts:1986:09:03:04".hour.must_equal 4
|
156
|
+
"test:ts:test_ts:1986:10:05:06:07".minute.must_equal 7
|
157
|
+
"test:ts:test_ts:1986:11:08:09:10:11".second.must_equal 11
|
158
|
+
end
|
159
|
+
|
160
|
+
it "recent" do
|
161
|
+
year = Time.now.year
|
162
|
+
month = Time.now.month
|
163
|
+
day = Time.now.day
|
164
|
+
hour = Time.now.hour
|
165
|
+
minute = Time.now.min
|
166
|
+
|
167
|
+
#year
|
168
|
+
"test:ts:test_ts:#{year+1}".recent?.must_equal false
|
169
|
+
"test:ts:test_ts:#{year}".recent?.must_equal true
|
170
|
+
|
171
|
+
#month
|
172
|
+
"test:ts:test_ts:#{year+1}:#{month}".recent?.must_equal false
|
173
|
+
"test:ts:test_ts:#{year}:#{month}".recent?.must_equal true
|
174
|
+
|
175
|
+
#second
|
176
|
+
"test:ts:test_ts:#{year}:#{month}:#{day}:#{hour}:#{minute+1}:10".recent?.must_equal false
|
177
|
+
"test:ts:test_ts:#{year}:#{month}:#{day}:#{hour}:#{minute}:10".recent?.must_equal true
|
178
|
+
end
|
179
|
+
|
180
|
+
|
181
|
+
it "get array and hash from redis" do
|
182
|
+
key = "test:ts:test_ts:1986"
|
183
|
+
@redis.zincrby "test:ts:test_ts:1986", 1, "one"
|
184
|
+
@redis.zincrby "test:ts:test_ts:1986", 2, "two"
|
185
|
+
@redis.zincrby "test:ts:test_ts:1986", 3, "three"
|
186
|
+
@redis.zincrby "test:ts:test_ts:1986", 4, "four"
|
187
|
+
@redis.zincrby "test:ts:test_ts:1986", 5, "five"
|
188
|
+
@redis.zincrby "test:ts:test_ts:1986", 6, "six"
|
189
|
+
@redis.zincrby "test:ts:test_ts:1986", 7, "seven"
|
190
|
+
key.get_array.must_be_instance_of Array
|
191
|
+
key.get.must_be_instance_of Hash
|
192
|
+
h = {"one"=>1, "two"=>2, "three"=>3, "four"=>4, "five"=>5, "six"=>6, "seven"=>7}
|
193
|
+
key.get.must_equal h
|
194
|
+
end
|
195
|
+
|
196
|
+
it "time from key" do
|
197
|
+
"test:ts:test_ts:1986".time.must_be_instance_of Time
|
198
|
+
"test:ts:test_ts:2000".time.year.must_equal 2000
|
199
|
+
"test:ts:test_ts:2001:01".time.month.must_equal 1
|
200
|
+
"test:ts:test_ts:2001:01:30:23:00:59".time.sec.must_equal 59
|
201
|
+
end
|
202
|
+
|
203
|
+
|
204
|
+
|
205
|
+
it "can return a non-existing key based on its children" do
|
206
|
+
key = "test:ts:test_ts:2000:12:30" #day
|
207
|
+
time = Time.new(2000, 12, 30)
|
208
|
+
|
209
|
+
keys = %w(
|
210
|
+
test:ts:test_ts:2000:12:30:01 test:ts:test_ts:2000:12:30:02 test:ts:test_ts:2000:12:30:03
|
211
|
+
test:ts:test_ts:2000:12:30:04 test:ts:test_ts:2000:12:30:05 test:ts:test_ts:2000:12:30:06
|
212
|
+
|
213
|
+
test:ts:test_ts:2000:12:30:07:01 test:ts:test_ts:2000:12:30:07:02 test:ts:test_ts:2000:12:30:07:03
|
214
|
+
|
215
|
+
test:ts:test_ts:2000:12:30:07:05:01 test:ts:test_ts:2000:12:30:07:01:05:02 test:ts:test_ts:2000:12:30:07:01:05:03
|
216
|
+
)
|
217
|
+
|
218
|
+
expire = %w( test:ts:test_ts:2000:12:30:01 test:ts:test_ts:2000:12:30:02 test:ts:test_ts:2000:12:30:06
|
219
|
+
test:ts:test_ts:2000:12:30:07:02 test:ts:test_ts:2000:12:30:07:01:05:02 test:ts:test_ts:2000:12:30:07:01:05:03
|
220
|
+
)
|
221
|
+
keys.each{|k| @redis.zincrby k, 1, "one"}
|
222
|
+
expire.each{|k| @redis.expire k, 1}
|
223
|
+
|
224
|
+
key.exists?.must_equal false # key does not exists
|
225
|
+
key.get.must_be_instance_of Hash # key is created from its children
|
226
|
+
key.exists?.must_equal true # now key exists
|
227
|
+
key.volatile?.must_equal true # key is volatile
|
228
|
+
key.get["one"].must_equal 6
|
229
|
+
end
|
230
|
+
|
231
|
+
it "can return a non-existing key without children based on its parent" do
|
232
|
+
key = "test:ts:test_ts:2000:12:30" #day
|
233
|
+
# 6 sibling days and 6 non children hours
|
234
|
+
keys = %w(
|
235
|
+
test:ts:test_ts:2000:12:29 test:ts:test_ts:2000:12:28 test:ts:test_ts:2000:12:27
|
236
|
+
test:ts:test_ts:2000:12:26 test:ts:test_ts:2000:12:25 test:ts:test_ts:2000:12:24
|
237
|
+
|
238
|
+
test:ts:test_ts:2000:12:31:01 test:ts:test_ts:2000:12:31:02 test:ts:test_ts:2000:12:31:03
|
239
|
+
test:ts:test_ts:2000:12:31:04 test:ts:test_ts:2000:12:31:05 test:ts:test_ts:2000:12:31:06
|
240
|
+
)
|
241
|
+
|
242
|
+
expire = %w( test:ts:test_ts:2000:12:29 test:ts:test_ts:2000:12:31:04 )
|
243
|
+
keys.each{|k| @redis.zincrby k, 1, "one"}
|
244
|
+
expire.each{|k| @redis.expire k, 10}
|
245
|
+
|
246
|
+
#ap key.parent.persistant_children
|
247
|
+
key.exists?.must_equal false
|
248
|
+
key.has_children?.must_equal false # key has no children, only siblings
|
249
|
+
key.get.must_be_instance_of Hash # get will be retrive info from its parent children
|
250
|
+
key.exists?.must_equal true
|
251
|
+
key.get["one"].must_equal 1
|
252
|
+
key.volatile?.must_equal true
|
253
|
+
|
254
|
+
end
|
255
|
+
|
256
|
+
end
|