time_series 0.0.1
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.
- 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
|