event-counter 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -2
- data/CHANGELOG.md +5 -1
- data/README.md +11 -8
- data/lib/event_counter.rb +9 -4
- data/lib/event_counter/version.rb +1 -1
- data/spec/lib/event_counter_spec.rb +20 -21
- data/spec/lib/performance_spec.rb +3 -3
- data/spec/support/matchers.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0bd855f0622ba4699ac98ae5f11d635fff270bbc
|
4
|
+
data.tar.gz: 996454629b26cf7eb0ce21338f5a5c443fd79713
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16a2277eeb66b50ca1110700ab4fc40497714b5fd928599e4310da1055ff62e38b44a4db6cd004f447bea28169219bb628f1a32c43265bd8e74f404a20a423f3
|
7
|
+
data.tar.gz: c67d8bcab89dcf2bdfd2f99b466e439269af57e13647c7fd13f93594efe4a19e1d49d4845e0d591080b5c31e0b4230e5c1f3e4ae0bdd6d8f20af31df2a5bb882
|
data/.travis.yml
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
-
- 1.9.3
|
4
3
|
- 2.0.0
|
5
4
|
- 2.1.0
|
6
5
|
|
@@ -10,7 +9,7 @@ gemfile:
|
|
10
9
|
- gemfiles/pg_ar_32.gemfile
|
11
10
|
- gemfiles/pg_ar_40.gemfile
|
12
11
|
|
13
|
-
script: RUN_ALL=true rspec spec
|
12
|
+
script: RUN_ALL=true bundle exec rspec spec
|
14
13
|
|
15
14
|
services:
|
16
15
|
- postgresql
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
[![Build Status](https://travis-ci.org/skyeagle/event-counter.svg)](https://travis-ci.org/skyeagle/event-counter)
|
2
|
+
|
1
3
|
# EventCounter
|
2
4
|
|
3
5
|
EventCounter is a database based event counter with throttling per time intervals.
|
@@ -69,8 +71,8 @@ article.data_for(:views, interval: 10.minutes)
|
|
69
71
|
# ]
|
70
72
|
|
71
73
|
# with range
|
72
|
-
range_start = Time.
|
73
|
-
range_end = Time.
|
74
|
+
range_start = Time.zone.local(2014, 10, 16, 23, 0)
|
75
|
+
range_end = Time.zone.local(2014, 10, 16, 23, 10)
|
74
76
|
range = range_start..range_end
|
75
77
|
article.data_for(:views, interval: 10.minutes, range: range)
|
76
78
|
#=> [
|
@@ -79,8 +81,8 @@ article.data_for(:views, interval: 10.minutes, range: range)
|
|
79
81
|
# ]
|
80
82
|
|
81
83
|
# for different time zone (although we have no data for that time)
|
82
|
-
range_start = Time.
|
83
|
-
range_end = Time.
|
84
|
+
range_start = Time.zone.local(2014, 10, 16, 23, 0).in_time_zone('UTC')
|
85
|
+
range_end = Time.zone.local(2014, 10, 16, 23, 10).in_time_zone('UTC')
|
84
86
|
range = range_start..range_end
|
85
87
|
article.data_for(:views, interval: 10.minutes, range: range, tz: 'UTC')
|
86
88
|
#=> [
|
@@ -98,8 +100,8 @@ article.data_for(:views, interval: :day, raw: true)
|
|
98
100
|
# looks as `Time.zone.parse(i['created_at']), i['value'].to_i ]`
|
99
101
|
|
100
102
|
# class wide
|
101
|
-
range_start = Time.
|
102
|
-
range_end = Time.
|
103
|
+
range_start = Time.zone.local(2014, 10, 15)
|
104
|
+
range_end = Time.zone.local(2014, 10, 16)
|
103
105
|
range = range_start..range_end
|
104
106
|
Article.data_for(:views, interval: :day, range: range)
|
105
107
|
# => [
|
@@ -111,6 +113,7 @@ Article.data_for(:views, interval: :day, range: range)
|
|
111
113
|
## Limitations
|
112
114
|
|
113
115
|
- It works *ONLY* with *PostgreSQL* at the moment.
|
116
|
+
- Ruby 2+
|
114
117
|
- ActiveRecord 3+
|
115
118
|
- ActiveSupport 3+
|
116
119
|
- It's polymorphic association.
|
@@ -142,9 +145,9 @@ class CreateEventCounters < ActiveRecord::Migration
|
|
142
145
|
t.datetime :created_at
|
143
146
|
end
|
144
147
|
|
145
|
-
add_index :event_counters, :
|
148
|
+
add_index :event_counters, :created_at
|
146
149
|
add_index :event_counters,
|
147
|
-
[:countable_type, :name, :countable_id], name: '
|
150
|
+
[:countable_type, :name, :countable_id], name: 'index_complex'
|
148
151
|
|
149
152
|
end
|
150
153
|
|
data/lib/event_counter.rb
CHANGED
@@ -27,7 +27,7 @@ class EventCounter < ActiveRecord::Base
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def self.make(val = 1, on_time: nil, force: false)
|
30
|
-
on_time = normalize_on_time(on_time)
|
30
|
+
on_time = normalize_on_time!(on_time)
|
31
31
|
|
32
32
|
attrs = { created_at: on_time }
|
33
33
|
|
@@ -52,7 +52,7 @@ class EventCounter < ActiveRecord::Base
|
|
52
52
|
|
53
53
|
val ||= 1
|
54
54
|
|
55
|
-
on_time = normalize_on_time(on_time)
|
55
|
+
on_time = normalize_on_time!(on_time)
|
56
56
|
|
57
57
|
counter = where(created_at: on_time).first
|
58
58
|
|
@@ -87,8 +87,11 @@ class EventCounter < ActiveRecord::Base
|
|
87
87
|
fail CounterError, args
|
88
88
|
end
|
89
89
|
|
90
|
-
def self.normalize_on_time(on_time)
|
90
|
+
def self.normalize_on_time!(on_time)
|
91
91
|
on_time ||= Time.zone.now
|
92
|
+
|
93
|
+
counter_error!(:time_zone) unless on_time.is_a?(ActiveSupport::TimeWithZone)
|
94
|
+
|
92
95
|
on_time =
|
93
96
|
case current_interval
|
94
97
|
when Symbol
|
@@ -108,7 +111,9 @@ class EventCounter < ActiveRecord::Base
|
|
108
111
|
less: 'Specified interval (%{interval}) could not be less then ' \
|
109
112
|
'a defined (%{default_interval}) in a countable model (%{model}).',
|
110
113
|
multiple: 'Specified interval (%{interval}) should be a multiple of ' \
|
111
|
-
'a defined (%{default_interval}) in a countable model (%{model}).'
|
114
|
+
'a defined (%{default_interval}) in a countable model (%{model}).',
|
115
|
+
time_zone: 'The :on_time option should be defined with time zone, e.x.: ' \
|
116
|
+
'Time.zone.local(2014, 1, 1, 1, 1)'
|
112
117
|
}
|
113
118
|
|
114
119
|
attr_accessor :extra
|
@@ -27,7 +27,7 @@ describe EventCounter do
|
|
27
27
|
end
|
28
28
|
|
29
29
|
it '#make on time' do
|
30
|
-
on_time = Time.
|
30
|
+
on_time = Time.zone.local(2014, 1, 1, 1, 14)
|
31
31
|
expect {
|
32
32
|
counter = ball.rotations.make(
|
33
33
|
3, on_time: on_time)
|
@@ -48,7 +48,7 @@ describe EventCounter do
|
|
48
48
|
end
|
49
49
|
|
50
50
|
it '#make on time with interval as symbol' do
|
51
|
-
on_time = Time.
|
51
|
+
on_time = Time.zone.local(2014, 1, 1, 1, 1)
|
52
52
|
[:week, :month, :year].each do |interval|
|
53
53
|
expect {
|
54
54
|
counter = ball.send(:"rotations_by_#{interval}").make(
|
@@ -80,13 +80,13 @@ describe Ball do
|
|
80
80
|
expect(ball.up!(:rotations)).to be_a(EventCounter)
|
81
81
|
}.to change { EventCounter.count }.by(1)
|
82
82
|
|
83
|
-
on_time = Time.
|
83
|
+
on_time = Time.zone.local(2011, 11, 11, 11, 11)
|
84
84
|
expect {
|
85
85
|
expect(ball.up!(:rotations, on_time: on_time))
|
86
86
|
.to be_a(EventCounter)
|
87
87
|
}.to change { EventCounter.count }.by(1)
|
88
88
|
|
89
|
-
on_time = Time.
|
89
|
+
on_time = Time.zone.local(2012, 12, 12, 12, 12)
|
90
90
|
expect {
|
91
91
|
expect(ball.up!(:rotations, 5, on_time: on_time))
|
92
92
|
.to be_a(EventCounter)
|
@@ -98,13 +98,13 @@ describe Ball do
|
|
98
98
|
expect(ball.down!(:rotations)).to be_a(EventCounter)
|
99
99
|
}.to change { EventCounter.count }.by(1)
|
100
100
|
|
101
|
-
on_time = Time.
|
101
|
+
on_time = Time.zone.local(2011, 11, 11, 11, 11)
|
102
102
|
expect {
|
103
103
|
expect(ball.down!(:rotations, on_time: on_time))
|
104
104
|
.to be_a(EventCounter)
|
105
105
|
}.to change { EventCounter.count }.by(1)
|
106
106
|
|
107
|
-
on_time = Time.
|
107
|
+
on_time = Time.zone.local(2012, 12, 12, 12, 12)
|
108
108
|
expect {
|
109
109
|
expect(ball.down!(:rotations, 5, on_time: on_time))
|
110
110
|
.to be_a(EventCounter)
|
@@ -152,7 +152,7 @@ describe Ball do
|
|
152
152
|
end
|
153
153
|
|
154
154
|
it 'increments existent counter on time with default value' do
|
155
|
-
on_time = Time.
|
155
|
+
on_time = Time.zone.local(2012, 12, 12, 12, 12)
|
156
156
|
counter = ball.rotations.make on_time: on_time
|
157
157
|
|
158
158
|
expect {
|
@@ -163,7 +163,7 @@ describe Ball do
|
|
163
163
|
end
|
164
164
|
|
165
165
|
it 'decrements existent counter on time with default value' do
|
166
|
-
on_time = Time.
|
166
|
+
on_time = Time.zone.local(2012, 12, 12, 12, 12)
|
167
167
|
counter = ball.rotations.make on_time: on_time
|
168
168
|
|
169
169
|
expect {
|
@@ -174,7 +174,7 @@ describe Ball do
|
|
174
174
|
end
|
175
175
|
|
176
176
|
it 'increments existent counter on time with specified value' do
|
177
|
-
on_time = Time.
|
177
|
+
on_time = Time.zone.local(2012, 12, 12, 12, 12)
|
178
178
|
counter = ball.rotations.make 2, on_time: on_time
|
179
179
|
|
180
180
|
expect {
|
@@ -185,7 +185,7 @@ describe Ball do
|
|
185
185
|
end
|
186
186
|
|
187
187
|
it 'decrements existent counter on time with specified value' do
|
188
|
-
on_time = Time.
|
188
|
+
on_time = Time.zone.local(2012, 12, 12, 12, 12)
|
189
189
|
counter = ball.rotations.make 2, on_time: on_time
|
190
190
|
|
191
191
|
expect {
|
@@ -207,7 +207,7 @@ describe Ball do
|
|
207
207
|
end
|
208
208
|
|
209
209
|
it 'forces existent counter on time with new value' do
|
210
|
-
on_time = Time.
|
210
|
+
on_time = Time.zone.local(2012, 12, 12, 12, 12)
|
211
211
|
counter = ball.rotations.make 2, on_time: on_time
|
212
212
|
|
213
213
|
expect {
|
@@ -230,7 +230,7 @@ describe Ball do
|
|
230
230
|
|
231
231
|
def setup_counters(countable_count = 1)
|
232
232
|
[1, 1, 2, 3, 5, 8, 13, 21, 34].each do |n|
|
233
|
-
on_time = Time.
|
233
|
+
on_time = Time.zone.local(2014, 1, 1, 1, n)
|
234
234
|
if countable_count == 1
|
235
235
|
ball.rotations.make n, on_time: on_time
|
236
236
|
else
|
@@ -282,8 +282,8 @@ describe Ball do
|
|
282
282
|
end
|
283
283
|
|
284
284
|
it 'with a greater interval and a time range' do
|
285
|
-
range_start = Time.
|
286
|
-
range_end = Time.
|
285
|
+
range_start = Time.zone.local 2014, 1, 1, 1, 15
|
286
|
+
range_end = Time.zone.local 2014, 1, 1, 1, 45
|
287
287
|
range = range_start.in_time_zone..range_end.in_time_zone
|
288
288
|
|
289
289
|
data = [ [ 10, 13 ], [ 20, 21 ], [ 30, 34 ], [ 40, 0] ]
|
@@ -293,7 +293,7 @@ describe Ball do
|
|
293
293
|
end
|
294
294
|
|
295
295
|
it 'with a greater interval as symbol' do
|
296
|
-
beginning_of_week = Time.
|
296
|
+
beginning_of_week = Time.zone.local(2014).beginning_of_week
|
297
297
|
|
298
298
|
data = [ [ beginning_of_week, 88 ] ]
|
299
299
|
|
@@ -333,8 +333,8 @@ describe Ball do
|
|
333
333
|
it 'with a greater interval within range' do
|
334
334
|
data = [ [ 10, 39 ], [ 20, 63 ] ]
|
335
335
|
|
336
|
-
range_start = Time.
|
337
|
-
range_end = Time.
|
336
|
+
range_start = Time.zone.local(2014, 1, 1, 1, 15)
|
337
|
+
range_end = Time.zone.local(2014, 1, 1, 1, 29)
|
338
338
|
range = range_start..range_end
|
339
339
|
|
340
340
|
expect(subject.data_for(:rotations, interval: 10.minutes, range: range))
|
@@ -342,7 +342,7 @@ describe Ball do
|
|
342
342
|
end
|
343
343
|
|
344
344
|
it 'with a greater interval as symbol and a simple data' do
|
345
|
-
bmonth = Time.
|
345
|
+
bmonth = Time.zone.local(2014, 1, 1).beginning_of_month
|
346
346
|
data = [ [ bmonth, 264 ] ]
|
347
347
|
|
348
348
|
expect(subject.data_for(:rotations, interval: :month))
|
@@ -350,7 +350,7 @@ describe Ball do
|
|
350
350
|
end
|
351
351
|
|
352
352
|
it 'with a greater interval as symbol and a simple data within range' do
|
353
|
-
bmonth = Time.
|
353
|
+
bmonth = Time.zone.local(2014, 1, 1).beginning_of_month
|
354
354
|
data = [ [ bmonth, 264 ] ]
|
355
355
|
|
356
356
|
range_start = bmonth
|
@@ -372,8 +372,7 @@ describe Ball do
|
|
372
372
|
end
|
373
373
|
end
|
374
374
|
|
375
|
-
data = (6..12).map { |x| [ Time.
|
376
|
-
|
375
|
+
data = (6..12).map { |x| [ Time.zone.local(2013, x), 264 ] }
|
377
376
|
range_start = data[0][0].beginning_of_month
|
378
377
|
range_end = data[-1][0].end_of_month
|
379
378
|
range = range_start..range_end
|
@@ -7,8 +7,8 @@ describe Ball, slow: true do
|
|
7
7
|
DatabaseCleaner.clean_with(:truncation)
|
8
8
|
end
|
9
9
|
|
10
|
-
let(:range_start) {
|
11
|
-
let(:range_end) {
|
10
|
+
let(:range_start) { Time.zone.local(2013, 7).beginning_of_month }
|
11
|
+
let(:range_end) { Time.zone.local(2014, 6).end_of_month }
|
12
12
|
let(:range) { range_start..range_end }
|
13
13
|
|
14
14
|
def disable_logging(&blk)
|
@@ -27,7 +27,7 @@ describe Ball, slow: true do
|
|
27
27
|
|
28
28
|
ball = Ball.create!
|
29
29
|
|
30
|
-
(Time.
|
30
|
+
(Time.zone.local(2012).to_i..Time.zone.local(2015).to_i).step(step) do |i|
|
31
31
|
on_time = Time.at(i)
|
32
32
|
ball.rotations.make on_time: on_time
|
33
33
|
end
|
data/spec/support/matchers.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: event-counter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anton Orel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-10-
|
11
|
+
date: 2014-10-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|