merry_go_round 0.0.5 → 0.0.6

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.
@@ -43,6 +43,16 @@ module MerryGoRound
43
43
 
44
44
  # Aggregate existing aggregations (i.e. hour -> day)
45
45
  def compound
46
+ # Get list of known keys
47
+ keys = Aggregation.select('DISTINCT(key) AS key').collect(&:key)
48
+
49
+ # Aggregate each key
50
+ keys.each do |key|
51
+ compound_key(key)
52
+ end
53
+ end
54
+
55
+ def compound_key(key)
46
56
  now = Time.now.utc
47
57
 
48
58
  # Loop through all of the granularities except for the first one
@@ -50,46 +60,60 @@ module MerryGoRound
50
60
  # Skip minutes since the Redis aggregator does those
51
61
  next if index == 0
52
62
 
63
+ # Get starting point
64
+ start = start_timestamp(key, granularity).to_i
65
+
53
66
  # Time interval for granularity
67
+ # TODO: Use `window` instead of `seconds`
54
68
  interval = seconds(granularity)
55
69
 
56
70
  # Get the previous granularity
57
71
  prev_gran = MerryGoRound.granularities[index - 1]
58
72
 
59
- # Get where we left off for this granularity
60
- results = Aggregation.select('MAX(timestamp) AS timestamp, key').where(granularity: prev_gran).group(:key).order('timestamp DESC')
61
-
62
73
  # Loop through the results
63
- results.each do |result|
64
- timestamp = result.timestamp.utc.to_i
65
- while timestamp < now.to_i
66
- range = window(granularity, Time.at(timestamp).utc)
67
- break unless range.first < now and range.last < now
68
-
69
- # Check time interval to see if we have enough data to do this granularity
70
- break if Aggregation.where('key = ? AND granularity = ? AND timestamp = ?', result.key, granularity, range.first).first
74
+ while start < now.to_i
75
+ range = window(granularity, Time.at(start).utc)
76
+ break unless range.first < now
71
77
 
72
- children = Aggregation.where('key = ? AND granularity = ? AND timestamp >= ? AND timestamp <= ?', result.key, prev_gran, range.first, range.last).order('timestamp ASC')
73
- break unless children.length > 0
78
+ # Check time interval to see if we have enough data to do this granularity
79
+ break if Aggregation.where('key = ? AND granularity = ? AND timestamp = ?', key, granularity, range.first).first
74
80
 
75
- # Get the aggregated value
76
- # TODO: This should probably done in SQL
77
- value = children.collect(&:value).reduce(:+)
81
+ children = Aggregation.where('key = ? AND granularity = ? AND timestamp >= ? AND timestamp <= ?', key, prev_gran, range.first, range.last).order('timestamp ASC')
82
+ break unless children.length > 0
78
83
 
79
- # Create the aggregation
80
- agg = Aggregation.create(key: result.key, value: value, granularity: granularity, timestamp: range.first)
84
+ # Get the aggregated value
85
+ # TODO: This should probably done in SQL
86
+ value = children.collect(&:value).reduce(:+)
81
87
 
82
- # Associate the children with their parent
83
- children.each do |child|
84
- child.parent_id = agg.id
85
- child.save
86
- end
88
+ # Create the aggregation
89
+ agg = Aggregation.create(key: key, value: value, granularity: granularity, timestamp: range.first)
87
90
 
88
- # Increment the timestamp
89
- timestamp += interval
91
+ # Associate the children with their parent
92
+ children.each do |child|
93
+ child.parent_id = agg.id
94
+ child.save
90
95
  end
96
+
97
+ # Increment the timestamp
98
+ start += interval
91
99
  end
92
100
  end
93
101
  end
102
+
103
+ def start_timestamp(key, granularity)
104
+ # Search at this level
105
+ result = Aggregation.select('MAX(timestamp) AS timestamp').where(key: key, granularity: granularity).order('timestamp DESC').first
106
+ if result and result.timestamp
107
+ # TODO: Possibily add 1
108
+ return result.timestamp
109
+ end
110
+
111
+ # Go down a level
112
+ prev_gran = MerryGoRound.granularities[MerryGoRound.granularities.index(granularity) - 1]
113
+ result = Aggregation.select('MIN(timestamp) AS timestamp').where(key: key, granularity: prev_gran).order('timestamp ASC').first
114
+ return result.timestamp if result and result.timestamp
115
+
116
+ nil
117
+ end
94
118
  end
95
119
  end
@@ -1,3 +1,3 @@
1
1
  module MerryGoRound
2
- VERSION = '0.0.5'
2
+ VERSION = '0.0.6'
3
3
  end
File without changes
@@ -0,0 +1,179 @@
1
+ key,value,timestamp,granularity
2
+ vote.create,17,2013-02-13 00:01:00,minute
3
+ vote.create,5,2013-02-13 00:02:00,minute
4
+ vote.create,15,2013-02-13 00:03:00,minute
5
+ vote.create,9,2013-02-13 00:04:00,minute
6
+ vote.create,6,2013-02-13 00:05:00,minute
7
+ vote.create,4,2013-02-13 00:06:00,minute
8
+ vote.create,6,2013-02-13 00:07:00,minute
9
+ vote.create,2,2013-02-13 00:08:00,minute
10
+ vote.create,2,2013-02-13 00:09:00,minute
11
+ vote.create,3,2013-02-13 00:10:00,minute
12
+ vote.create,8,2013-02-13 00:11:00,minute
13
+ vote.create,8,2013-02-13 00:12:00,minute
14
+ vote.create,7,2013-02-13 00:13:00,minute
15
+ vote.create,15,2013-02-13 00:14:00,minute
16
+ vote.create,10,2013-02-13 00:15:00,minute
17
+ vote.create,2,2013-02-13 00:16:00,minute
18
+ vote.create,15,2013-02-13 00:17:00,minute
19
+ vote.create,13,2013-02-13 00:18:00,minute
20
+ vote.create,24,2013-02-13 00:19:00,minute
21
+ vote.create,20,2013-02-13 00:20:00,minute
22
+ vote.create,19,2013-02-13 00:21:00,minute
23
+ vote.create,24,2013-02-13 00:22:00,minute
24
+ vote.create,17,2013-02-13 00:23:00,minute
25
+ vote.create,9,2013-02-13 00:24:00,minute
26
+ vote.create,16,2013-02-13 00:25:00,minute
27
+ vote.create,12,2013-02-13 00:26:00,minute
28
+ vote.create,18,2013-02-13 00:27:00,minute
29
+ vote.create,19,2013-02-13 00:28:00,minute
30
+ vote.create,11,2013-02-13 00:29:00,minute
31
+ vote.create,8,2013-02-13 00:30:00,minute
32
+ vote.create,2,2013-02-13 00:31:00,minute
33
+ vote.create,6,2013-02-13 00:32:00,minute
34
+ vote.create,12,2013-02-13 00:33:00,minute
35
+ vote.create,11,2013-02-13 00:34:00,minute
36
+ vote.create,8,2013-02-13 00:35:00,minute
37
+ vote.create,3,2013-02-13 00:36:00,minute
38
+ vote.create,3,2013-02-13 00:37:00,minute
39
+ vote.create,2,2013-02-13 00:38:00,minute
40
+ vote.create,16,2013-02-13 00:39:00,minute
41
+ vote.create,16,2013-02-13 00:40:00,minute
42
+ vote.create,25,2013-02-13 00:41:00,minute
43
+ vote.create,25,2013-02-13 00:42:00,minute
44
+ vote.create,14,2013-02-13 00:43:00,minute
45
+ vote.create,11,2013-02-13 00:44:00,minute
46
+ vote.create,10,2013-02-13 00:45:00,minute
47
+ vote.create,3,2013-02-13 00:46:00,minute
48
+ vote.create,12,2013-02-13 00:47:00,minute
49
+ vote.create,12,2013-02-13 00:48:00,minute
50
+ vote.create,25,2013-02-13 00:49:00,minute
51
+ vote.create,36,2013-02-13 00:50:00,minute
52
+ vote.create,32,2013-02-13 00:51:00,minute
53
+ vote.create,18,2013-02-13 00:52:00,minute
54
+ vote.create,13,2013-02-13 00:53:00,minute
55
+ vote.create,9,2013-02-13 00:54:00,minute
56
+ vote.create,21,2013-02-13 00:55:00,minute
57
+ vote.create,19,2013-02-13 00:56:00,minute
58
+ vote.create,10,2013-02-13 00:57:00,minute
59
+ vote.create,11,2013-02-13 00:58:00,minute
60
+ vote.create,8,2013-02-13 00:59:00,minute
61
+ vote.create,27,2013-02-13 01:00:00,minute
62
+ vote.create,14,2013-02-13 01:01:00,minute
63
+ vote.create,14,2013-02-13 01:02:00,minute
64
+ vote.create,12,2013-02-13 01:03:00,minute
65
+ vote.create,1,2013-02-13 01:04:00,minute
66
+ vote.create,4,2013-02-13 01:05:00,minute
67
+ vote.create,20,2013-02-13 01:06:00,minute
68
+ vote.create,15,2013-02-13 01:07:00,minute
69
+ vote.create,6,2013-02-13 01:08:00,minute
70
+ vote.create,14,2013-02-13 01:09:00,minute
71
+ vote.create,11,2013-02-13 01:10:00,minute
72
+ vote.create,9,2013-02-13 01:11:00,minute
73
+ vote.create,7,2013-02-13 01:12:00,minute
74
+ vote.create,16,2013-02-13 01:13:00,minute
75
+ vote.create,10,2013-02-13 01:14:00,minute
76
+ vote.create,4,2013-02-13 01:15:00,minute
77
+ vote.create,7,2013-02-13 01:16:00,minute
78
+ vote.create,1,2013-02-13 01:17:00,minute
79
+ vote.create,4,2013-02-13 01:18:00,minute
80
+ vote.create,10,2013-02-13 01:19:00,minute
81
+ vote.create,5,2013-02-13 01:20:00,minute
82
+ vote.create,7,2013-02-13 01:21:00,minute
83
+ vote.create,10,2013-02-13 01:22:00,minute
84
+ vote.create,10,2013-02-13 01:23:00,minute
85
+ vote.create,11,2013-02-13 01:24:00,minute
86
+ vote.create,3,2013-02-13 01:25:00,minute
87
+ vote.create,5,2013-02-13 01:26:00,minute
88
+ vote.create,6,2013-02-13 01:27:00,minute
89
+ vote.create,1,2013-02-13 01:28:00,minute
90
+ vote.create,3,2013-02-13 01:29:00,minute
91
+ vote.create,14,2013-02-13 01:30:00,minute
92
+ vote.create,7,2013-02-13 01:31:00,minute
93
+ vote.create,5,2013-02-13 01:32:00,minute
94
+ vote.create,2,2013-02-13 01:33:00,minute
95
+ vote.create,8,2013-02-13 01:34:00,minute
96
+ vote.create,7,2013-02-13 01:35:00,minute
97
+ vote.create,6,2013-02-13 01:37:00,minute
98
+ vote.create,14,2013-02-13 01:38:00,minute
99
+ vote.create,10,2013-02-13 01:39:00,minute
100
+ vote.create,17,2013-02-13 01:40:00,minute
101
+ vote.create,7,2013-02-13 01:41:00,minute
102
+ vote.create,3,2013-02-13 01:42:00,minute
103
+ vote.create,8,2013-02-13 01:43:00,minute
104
+ vote.create,15,2013-02-13 01:44:00,minute
105
+ vote.create,18,2013-02-13 01:45:00,minute
106
+ vote.create,11,2013-02-13 01:46:00,minute
107
+ vote.create,7,2013-02-13 01:47:00,minute
108
+ vote.create,10,2013-02-13 01:48:00,minute
109
+ vote.create,15,2013-02-13 01:49:00,minute
110
+ vote.create,11,2013-02-13 01:50:00,minute
111
+ vote.create,9,2013-02-13 01:51:00,minute
112
+ vote.create,4,2013-02-13 01:52:00,minute
113
+ vote.create,3,2013-02-13 01:53:00,minute
114
+ vote.create,2,2013-02-13 01:54:00,minute
115
+ vote.create,3,2013-02-13 01:55:00,minute
116
+ vote.create,10,2013-02-13 01:56:00,minute
117
+ vote.create,12,2013-02-13 01:57:00,minute
118
+ vote.create,8,2013-02-13 01:58:00,minute
119
+ vote.create,15,2013-02-13 01:59:00,minute
120
+ vote.create,24,2013-02-13 02:00:00,minute
121
+ vote.create,24,2013-02-13 02:01:00,minute
122
+ vote.create,12,2013-02-13 02:02:00,minute
123
+ vote.create,2,2013-02-13 02:02:00,minute
124
+ vote.create,9,2013-02-13 02:03:00,minute
125
+ vote.create,3,2013-02-13 02:04:00,minute
126
+ vote.create,3,2013-02-13 02:05:00,minute
127
+ vote.create,3,2013-02-13 02:06:00,minute
128
+ vote.create,5,2013-02-13 02:07:00,minute
129
+ vote.create,4,2013-02-13 02:08:00,minute
130
+ vote.create,6,2013-02-13 02:09:00,minute
131
+ vote.create,6,2013-02-13 02:10:00,minute
132
+ vote.create,11,2013-02-13 02:11:00,minute
133
+ vote.create,18,2013-02-13 02:12:00,minute
134
+ vote.create,12,2013-02-13 02:13:00,minute
135
+ vote.create,22,2013-02-13 02:14:00,minute
136
+ vote.create,10,2013-02-13 02:15:00,minute
137
+ vote.create,21,2013-02-13 02:16:00,minute
138
+ vote.create,14,2013-02-13 02:17:00,minute
139
+ vote.create,16,2013-02-13 02:18:00,minute
140
+ vote.create,17,2013-02-13 02:19:00,minute
141
+ vote.create,16,2013-02-13 02:20:00,minute
142
+ vote.create,15,2013-02-13 02:21:00,minute
143
+ vote.create,21,2013-02-13 02:22:00,minute
144
+ vote.create,4,2013-02-13 02:23:00,minute
145
+ vote.create,6,2013-02-13 02:24:00,minute
146
+ vote.create,11,2013-02-13 02:25:00,minute
147
+ vote.create,13,2013-02-13 02:26:00,minute
148
+ vote.create,31,2013-02-13 02:27:00,minute
149
+ vote.create,22,2013-02-13 02:28:00,minute
150
+ vote.create,21,2013-02-13 02:29:00,minute
151
+ vote.create,18,2013-02-13 02:30:00,minute
152
+ vote.create,23,2013-02-13 02:31:00,minute
153
+ vote.create,9,2013-02-13 02:32:00,minute
154
+ vote.create,17,2013-02-13 02:33:00,minute
155
+ vote.create,15,2013-02-13 02:34:00,minute
156
+ vote.create,9,2013-02-13 02:35:00,minute
157
+ vote.create,11,2013-02-13 02:36:00,minute
158
+ vote.create,5,2013-02-13 02:37:00,minute
159
+ vote.create,11,2013-02-13 02:38:00,minute
160
+ vote.create,25,2013-02-13 02:39:00,minute
161
+ vote.create,18,2013-02-13 02:40:00,minute
162
+ vote.create,6,2013-02-13 02:41:00,minute
163
+ vote.create,2,2013-02-13 02:42:00,minute
164
+ vote.create,1,2013-02-13 02:43:00,minute
165
+ vote.create,1,2013-02-13 02:44:00,minute
166
+ vote.create,2,2013-02-13 02:45:00,minute
167
+ vote.create,1,2013-02-13 02:47:00,minute
168
+ vote.create,2,2013-02-13 02:48:00,minute
169
+ vote.create,7,2013-02-13 02:49:00,minute
170
+ vote.create,6,2013-02-13 02:50:00,minute
171
+ vote.create,10,2013-02-13 02:51:00,minute
172
+ vote.create,12,2013-02-13 02:52:00,minute
173
+ vote.create,9,2013-02-13 02:53:00,minute
174
+ vote.create,14,2013-02-13 02:54:00,minute
175
+ vote.create,16,2013-02-13 02:55:00,minute
176
+ vote.create,20,2013-02-13 02:56:00,minute
177
+ vote.create,9,2013-02-13 02:57:00,minute
178
+ vote.create,11,2013-02-13 02:58:00,minute
179
+ vote.create,3,2013-02-13 02:59:00,minute
@@ -5,7 +5,7 @@ module MerryGoRound
5
5
  def test_aggregating_from_redis
6
6
  # Load the fixture. There is 60 minutes of data with 3 keys in each minute
7
7
  Timecop.freeze(Time.at(1360695600).utc) do
8
- redis_fixture('hour')
8
+ redis_fixture('minutes')
9
9
  MerryGoRound.aggregate!
10
10
  MerryGoRound.aggregate!
11
11
  end
@@ -16,12 +16,20 @@ module MerryGoRound
16
16
  # 1 hour * 3 keys
17
17
  assert_equal 3, Aggregation.where(granularity: 'hour').count
18
18
 
19
- # No days since there is only an hour of data
20
- assert_equal 0, Aggregation.where(granularity: 'day').count
21
-
22
19
  # The minute aggregations should belong to an hour one
23
20
  refute_nil Aggregation.where(granularity: 'minute').first.parent_id
24
21
  assert_equal 'hour', Aggregation.where(granularity: 'minute').first.parent.granularity
25
22
  end
23
+
24
+ def test_compound_aggregations
25
+ Timecop.freeze(Time.at(1360792056).utc) do
26
+ csv_fixture('votes')
27
+ MerryGoRound.aggregate!
28
+ assert_equal 3, Aggregation.where(granularity: 'hour').count
29
+
30
+ MerryGoRound.aggregate!
31
+ assert_equal 3, Aggregation.where(granularity: 'hour').count
32
+ end
33
+ end
26
34
  end
27
35
  end
@@ -4,7 +4,7 @@ module MerryGoRound
4
4
  class QueryTest < TestCase
5
5
  def test_execute
6
6
  Timecop.freeze(Time.at(1360695600).utc) do
7
- redis_fixture('hour')
7
+ redis_fixture('minutes')
8
8
  MerryGoRound.aggregate!
9
9
  end
10
10
 
@@ -1,11 +1,13 @@
1
+ require 'csv'
2
+
1
3
  module FixtureMacros
2
- def fixture(name)
4
+ def yml_fixture(name)
3
5
  path = File.expand_path("../../fixtures/#{name}.yml", __FILE__)
4
6
  YAML::load(File.open(path))
5
7
  end
6
8
 
7
9
  def redis_fixture(name)
8
- hash = fixture(name)
10
+ hash = yml_fixture(name)
9
11
  redis = MerryGoRound.redis
10
12
 
11
13
  hash.each do |key, value|
@@ -14,4 +16,11 @@ module FixtureMacros
14
16
  end
15
17
  end
16
18
  end
19
+
20
+ def csv_fixture(name)
21
+ path = File.expand_path("../../fixtures/#{name}.csv", __FILE__)
22
+ CSV.foreach(path) do |row|
23
+ MerryGoRound::Aggregation.create(key: row[0], value: row[1], timestamp: row[2], granularity: row[3])
24
+ end
25
+ end
17
26
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: merry_go_round
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -120,7 +120,8 @@ files:
120
120
  - lib/rails/generators/merry_go_round/install/templates/add_aggregations.rb
121
121
  - lib/rails/generators/merry_go_round/install/templates/merry_go_round.rake
122
122
  - merry_go_round.gemspec
123
- - test/fixtures/hour.yml
123
+ - test/fixtures/minutes.yml
124
+ - test/fixtures/votes.csv
124
125
  - test/merry_go_round/aggregation_test.rb
125
126
  - test/merry_go_round/aggregator_test.rb
126
127
  - test/merry_go_round/query_test.rb
@@ -152,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
152
153
  version: '0'
153
154
  segments:
154
155
  - 0
155
- hash: 3985102410336867870
156
+ hash: -2084216448482753946
156
157
  requirements: []
157
158
  rubyforge_project:
158
159
  rubygems_version: 1.8.23
@@ -160,7 +161,8 @@ signing_key:
160
161
  specification_version: 3
161
162
  summary: Simple data-warehousing with Redis and PostgreSQL.
162
163
  test_files:
163
- - test/fixtures/hour.yml
164
+ - test/fixtures/minutes.yml
165
+ - test/fixtures/votes.csv
164
166
  - test/merry_go_round/aggregation_test.rb
165
167
  - test/merry_go_round/aggregator_test.rb
166
168
  - test/merry_go_round/query_test.rb