abaci 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +7 -0
- data/lib/abaci.rb +31 -0
- data/lib/abaci/counter.rb +11 -13
- data/lib/abaci/date_range.rb +41 -0
- data/lib/abaci/metric.rb +15 -0
- data/lib/abaci/store.rb +23 -3
- data/lib/abaci/version.rb +1 -1
- data/test/counter_test.rb +199 -0
- data/test/date_range_test.rb +95 -0
- data/test/helper.rb +23 -0
- data/test/store_test.rb +81 -0
- metadata +7 -1
data/CHANGELOG.md
CHANGED
data/lib/abaci.rb
CHANGED
@@ -2,6 +2,8 @@ require 'abaci/version'
|
|
2
2
|
|
3
3
|
module Abaci
|
4
4
|
autoload :Counter, 'abaci/counter'
|
5
|
+
autoload :DateRange, 'abaci/date_range'
|
6
|
+
autoload :Metric, 'abaci/metric'
|
5
7
|
autoload :Store, 'abaci/store'
|
6
8
|
|
7
9
|
# Configuration options
|
@@ -10,6 +12,11 @@ module Abaci
|
|
10
12
|
Counter[key]
|
11
13
|
end
|
12
14
|
|
15
|
+
# Gets all specific metrics stored, without date-specific keys
|
16
|
+
def metrics
|
17
|
+
Metric.all
|
18
|
+
end
|
19
|
+
|
13
20
|
def options
|
14
21
|
@options ||= {
|
15
22
|
:redis => nil,
|
@@ -17,12 +24,36 @@ module Abaci
|
|
17
24
|
}
|
18
25
|
end
|
19
26
|
|
27
|
+
def prefix=(value)
|
28
|
+
@store = nil
|
29
|
+
options[:prefix] = value
|
30
|
+
end
|
31
|
+
|
20
32
|
def prefix
|
21
33
|
options[:prefix]
|
22
34
|
end
|
23
35
|
|
36
|
+
def redis=(value)
|
37
|
+
@store = nil
|
38
|
+
options[:redis] = value
|
39
|
+
end
|
40
|
+
|
24
41
|
def store
|
25
42
|
@store ||= Store.new(options)
|
26
43
|
end
|
44
|
+
alias_method :redis, :store
|
45
|
+
|
46
|
+
def summary
|
47
|
+
Counter.all
|
48
|
+
end
|
49
|
+
|
50
|
+
def method_missing(method, *args)
|
51
|
+
Counter.send(method, *args)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Alias Stat to Abaci::Counter if nothing else is using the Stat namespace
|
56
|
+
unless defined?(::Stat)
|
57
|
+
::Stat = Counter
|
27
58
|
end
|
28
59
|
end
|
data/lib/abaci/counter.rb
CHANGED
@@ -18,6 +18,7 @@ module Abaci
|
|
18
18
|
|
19
19
|
def del
|
20
20
|
keys.each { |k| Abaci.store.del(k) }
|
21
|
+
Metric.remove(key)
|
21
22
|
true
|
22
23
|
end
|
23
24
|
|
@@ -27,9 +28,7 @@ module Abaci
|
|
27
28
|
end
|
28
29
|
|
29
30
|
def get_last_days(number_of_days = 30)
|
30
|
-
|
31
|
-
start = (Date.today - Rational(seconds, 86400)).to_date
|
32
|
-
dates = (start..Date.today).map { |d| d.strftime('%Y:%-m:%-d') }
|
31
|
+
dates = DateRange.ago(number_of_days).keys
|
33
32
|
dates.map { |date| Abaci.store.get("#{key}:#{date}" ).to_i }.reduce(:+)
|
34
33
|
end
|
35
34
|
|
@@ -40,6 +39,7 @@ module Abaci
|
|
40
39
|
|
41
40
|
def increment_at(date = nil, by = 1)
|
42
41
|
date = Time.now unless date.respond_to?(:strftime)
|
42
|
+
Metric.add(key)
|
43
43
|
run(:incrby, by, date)
|
44
44
|
end
|
45
45
|
|
@@ -50,9 +50,14 @@ module Abaci
|
|
50
50
|
## Class methods ##
|
51
51
|
############################################################################
|
52
52
|
|
53
|
+
# Alias for Counter#new(key)
|
54
|
+
def self.[](key)
|
55
|
+
Counter.new(key)
|
56
|
+
end
|
57
|
+
|
53
58
|
# Returns a hash of all current values
|
54
59
|
def self.all
|
55
|
-
|
60
|
+
Metric.all.inject({}) { |hash, key| hash[key.to_sym] = Abaci.store.get(key).to_i; hash }
|
56
61
|
end
|
57
62
|
|
58
63
|
# Gets all currently logged stat keys
|
@@ -60,11 +65,6 @@ module Abaci
|
|
60
65
|
Abaci.store.keys(search).sort
|
61
66
|
end
|
62
67
|
|
63
|
-
# Alias for Counter#new(key)
|
64
|
-
def self.[](key)
|
65
|
-
Counter.new(key)
|
66
|
-
end
|
67
|
-
|
68
68
|
def self.method_missing(method, *args)
|
69
69
|
ms = method.to_s.downcase.strip
|
70
70
|
|
@@ -74,11 +74,9 @@ module Abaci
|
|
74
74
|
return self[$2].del
|
75
75
|
elsif ms =~ /^last_(\d*)_days_of_([a-z_]*)$/
|
76
76
|
return self[$2].get_last_days($1)
|
77
|
-
|
78
|
-
|
77
|
+
else
|
78
|
+
self[ms].get(*args)
|
79
79
|
end
|
80
|
-
|
81
|
-
super
|
82
80
|
end
|
83
81
|
|
84
82
|
## Protected methods ##
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Abaci
|
2
|
+
class DateRange
|
3
|
+
attr_reader :start, :finish
|
4
|
+
|
5
|
+
def initialize(start, finish)
|
6
|
+
if start < finish
|
7
|
+
@start = start
|
8
|
+
@finish = finish
|
9
|
+
else
|
10
|
+
@start = finish
|
11
|
+
@finish = start
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def days
|
16
|
+
range.to_a
|
17
|
+
end
|
18
|
+
|
19
|
+
def keys
|
20
|
+
days.map { |d| d.strftime('%Y:%-m:%-d') }
|
21
|
+
end
|
22
|
+
|
23
|
+
def range
|
24
|
+
start..finish
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.ago(days = 30)
|
28
|
+
seconds = days.to_i * 86400
|
29
|
+
start = (Date.today - Rational(seconds, 86400)).to_date
|
30
|
+
new(start, Date.today)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.between(start, finish)
|
34
|
+
new(start, finish)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.since(date)
|
38
|
+
new(date, Date.today)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/abaci/metric.rb
ADDED
data/lib/abaci/store.rb
CHANGED
@@ -4,6 +4,8 @@ module Abaci
|
|
4
4
|
# Common interface for Redis. In the future this could be
|
5
5
|
# swapped out for an alternate datastore.
|
6
6
|
class Store
|
7
|
+
attr_reader :prefix, :redis
|
8
|
+
|
7
9
|
def initialize(options)
|
8
10
|
@redis = options[:redis] || Redis.current
|
9
11
|
@prefix = options[:prefix] || 'ab'
|
@@ -25,8 +27,8 @@ module Abaci
|
|
25
27
|
exec(:incrby, key, by)
|
26
28
|
end
|
27
29
|
|
28
|
-
def keys(pattern)
|
29
|
-
sub = Regexp.new("^#{
|
30
|
+
def keys(pattern = "*")
|
31
|
+
sub = Regexp.new("^#{prefix}:")
|
30
32
|
exec(:keys, pattern).map { |k| k.gsub(sub, '') }
|
31
33
|
end
|
32
34
|
|
@@ -34,6 +36,18 @@ module Abaci
|
|
34
36
|
exec(:set, key, value)
|
35
37
|
end
|
36
38
|
|
39
|
+
def sadd(key, member)
|
40
|
+
exec_without_prefix(:sadd, "#{prefix}-#{key}", member)
|
41
|
+
end
|
42
|
+
|
43
|
+
def smembers(key)
|
44
|
+
exec_without_prefix(:smembers, "#{prefix}-#{key}")
|
45
|
+
end
|
46
|
+
|
47
|
+
def srem(key, member)
|
48
|
+
exec_without_prefix(:srem, "#{prefix}-#{key}", member)
|
49
|
+
end
|
50
|
+
|
37
51
|
protected
|
38
52
|
def exec(command, key, *args)
|
39
53
|
if @redis and @redis.respond_to?(command)
|
@@ -41,8 +55,14 @@ module Abaci
|
|
41
55
|
end
|
42
56
|
end
|
43
57
|
|
58
|
+
def exec_without_prefix(command, key, *args)
|
59
|
+
if @redis and @redis.respond_to?(command)
|
60
|
+
@redis.send(command, key, *args)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
44
64
|
def prefixed_key(key)
|
45
|
-
[
|
65
|
+
[ prefix, key ].compact.join(':')
|
46
66
|
end
|
47
67
|
end
|
48
68
|
end
|
data/lib/abaci/version.rb
CHANGED
@@ -0,0 +1,199 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class CounterTest < Test::Unit::TestCase
|
4
|
+
context "A counter" do
|
5
|
+
should "increment a stat" do
|
6
|
+
assert_equal 0, Abaci['testers'].get
|
7
|
+
|
8
|
+
Abaci['testers'].increment
|
9
|
+
|
10
|
+
assert_equal 1, Abaci['testers'].get
|
11
|
+
|
12
|
+
Abaci['testers'].increment(2)
|
13
|
+
|
14
|
+
assert_equal 3, Abaci['testers'].get
|
15
|
+
end
|
16
|
+
|
17
|
+
should "decrement a stat" do
|
18
|
+
assert_equal 0, Abaci['testers'].get
|
19
|
+
|
20
|
+
Abaci['testers'].increment(5)
|
21
|
+
assert_equal 5, Abaci['testers'].get
|
22
|
+
|
23
|
+
Abaci['testers'].decrement
|
24
|
+
assert_equal 4, Abaci['testers'].get
|
25
|
+
|
26
|
+
Abaci['testers'].decrement(2)
|
27
|
+
assert_equal 2, Abaci['testers'].get
|
28
|
+
end
|
29
|
+
|
30
|
+
should "increment a stat down to the minute" do
|
31
|
+
now = Time.now
|
32
|
+
|
33
|
+
Abaci['people'].increment
|
34
|
+
|
35
|
+
expected_keys = [
|
36
|
+
'people',
|
37
|
+
"people:#{now.strftime('%Y')}",
|
38
|
+
"people:#{now.strftime('%Y:%-m')}",
|
39
|
+
"people:#{now.strftime('%Y:%-m:%-d')}",
|
40
|
+
"people:#{now.strftime('%Y:%-m:%-d:%-k')}",
|
41
|
+
"people:#{now.strftime('%Y:%-m:%-d:%-k:%-M')}"
|
42
|
+
].sort
|
43
|
+
|
44
|
+
assert_equal expected_keys, Abaci['people'].keys.sort
|
45
|
+
|
46
|
+
assert_equal 1, Abaci['people'].get
|
47
|
+
assert_equal 1, Abaci['people'].get(now.year)
|
48
|
+
assert_equal 1, Abaci['people'].get(now.year, now.month)
|
49
|
+
assert_equal 1, Abaci['people'].get(now.year, now.month, now.day)
|
50
|
+
assert_equal 1, Abaci['people'].get(now.year, now.month, now.day, now.hour)
|
51
|
+
assert_equal 1, Abaci['people'].get(now.year, now.month, now.day, now.hour, now.min)
|
52
|
+
end
|
53
|
+
|
54
|
+
should "increment a stat at a certain date" do
|
55
|
+
time = Time.new(2012, 2, 29, 23, 29)
|
56
|
+
|
57
|
+
Abaci['people'].increment_at(time)
|
58
|
+
|
59
|
+
expected_keys = [
|
60
|
+
'people',
|
61
|
+
"people:2012",
|
62
|
+
"people:2012:2",
|
63
|
+
"people:2012:2:29",
|
64
|
+
"people:2012:2:29:23",
|
65
|
+
"people:2012:2:29:23:29"
|
66
|
+
].sort
|
67
|
+
|
68
|
+
assert_equal expected_keys, Abaci['people'].keys.sort
|
69
|
+
|
70
|
+
assert_equal 1, Abaci['people'].get
|
71
|
+
assert_equal 1, Abaci['people'].get(2012)
|
72
|
+
assert_equal 1, Abaci['people'].get(2012, 2)
|
73
|
+
assert_equal 1, Abaci['people'].get(2012, 2, 29)
|
74
|
+
assert_equal 1, Abaci['people'].get(2012, 2, 29, 23)
|
75
|
+
assert_equal 1, Abaci['people'].get(2012, 2, 29, 23, 29)
|
76
|
+
end
|
77
|
+
|
78
|
+
should "get stats summary for last 5 days" do
|
79
|
+
time = Time.new(2012, 5, 30, 5, 0)
|
80
|
+
time2 = Time.new(2012, 5, 31, 5, 0)
|
81
|
+
time3 = Time.new(2012, 6, 1, 5, 0)
|
82
|
+
time4 = Time.new(2012, 6, 2, 5, 0)
|
83
|
+
|
84
|
+
Abaci['people'].increment_at(time)
|
85
|
+
Abaci['people'].increment_at(time2)
|
86
|
+
Abaci['people'].increment_at(time3)
|
87
|
+
Abaci['people'].increment_at(time4)
|
88
|
+
Abaci['people'].increment
|
89
|
+
|
90
|
+
Date.stubs(:today).returns(Date.new(2012, 6, 2))
|
91
|
+
|
92
|
+
assert_equal 5, Abaci['people'].get
|
93
|
+
assert_equal 4, Abaci['people'].get_last_days(30)
|
94
|
+
assert_equal 3, Abaci['people'].get_last_days(2)
|
95
|
+
assert_equal 2, Abaci['people'].get_last_days(1)
|
96
|
+
|
97
|
+
Date.unstub(:today)
|
98
|
+
end
|
99
|
+
|
100
|
+
should "delete stats for a given key" do
|
101
|
+
time = Time.new(2012, 2, 29, 23, 29)
|
102
|
+
|
103
|
+
Abaci['people'].increment_at(time)
|
104
|
+
|
105
|
+
expected_keys = [
|
106
|
+
'people',
|
107
|
+
"people:2012",
|
108
|
+
"people:2012:2",
|
109
|
+
"people:2012:2:29",
|
110
|
+
"people:2012:2:29:23",
|
111
|
+
"people:2012:2:29:23:29"
|
112
|
+
].sort
|
113
|
+
|
114
|
+
assert_equal expected_keys, Abaci['people'].keys.sort
|
115
|
+
|
116
|
+
Abaci['people'].del
|
117
|
+
|
118
|
+
assert_equal [], Abaci['people'].keys
|
119
|
+
end
|
120
|
+
|
121
|
+
should "return all stat keys across all metrics" do
|
122
|
+
time = Time.new(2012, 2, 29, 23, 29)
|
123
|
+
|
124
|
+
Abaci['people'].increment_at(time)
|
125
|
+
Abaci['places'].increment_at(time)
|
126
|
+
Abaci['things'].increment_at(time)
|
127
|
+
|
128
|
+
expected_keys = [
|
129
|
+
'people',
|
130
|
+
"people:2012",
|
131
|
+
"people:2012:2",
|
132
|
+
"people:2012:2:29",
|
133
|
+
"people:2012:2:29:23",
|
134
|
+
"people:2012:2:29:23:29",
|
135
|
+
'places',
|
136
|
+
"places:2012",
|
137
|
+
"places:2012:2",
|
138
|
+
"places:2012:2:29",
|
139
|
+
"places:2012:2:29:23",
|
140
|
+
"places:2012:2:29:23:29",
|
141
|
+
'things',
|
142
|
+
"things:2012",
|
143
|
+
"things:2012:2",
|
144
|
+
"things:2012:2:29",
|
145
|
+
"things:2012:2:29:23",
|
146
|
+
"things:2012:2:29:23:29"
|
147
|
+
].sort
|
148
|
+
|
149
|
+
assert_equal expected_keys, Abaci.keys.sort
|
150
|
+
end
|
151
|
+
|
152
|
+
should "return all metrics stores, without date-specific keys" do
|
153
|
+
time = Time.new(2012, 2, 29, 23, 29)
|
154
|
+
|
155
|
+
Abaci['people'].increment_at(time)
|
156
|
+
Abaci['places'].increment_at(time)
|
157
|
+
Abaci['things'].increment_at(time)
|
158
|
+
|
159
|
+
expected_keys = %w( people places things ).sort
|
160
|
+
|
161
|
+
assert_equal expected_keys, Abaci.metrics.sort
|
162
|
+
end
|
163
|
+
|
164
|
+
should "return a hash of all top-level metrics and current values" do
|
165
|
+
Abaci['people'].increment
|
166
|
+
Abaci['places'].increment
|
167
|
+
Abaci['things'].increment(2)
|
168
|
+
|
169
|
+
expected_result = {
|
170
|
+
:people => 1,
|
171
|
+
:places => 1,
|
172
|
+
:things => 2
|
173
|
+
}
|
174
|
+
|
175
|
+
assert_equal expected_result, Abaci.summary
|
176
|
+
end
|
177
|
+
|
178
|
+
should "have handy shortcuts for incrementing simple metrics" do
|
179
|
+
Abaci.increment_people
|
180
|
+
Abaci.increment_places(2)
|
181
|
+
Abaci.increase_things
|
182
|
+
Abaci.incr_people
|
183
|
+
|
184
|
+
assert_equal 2, Abaci.people
|
185
|
+
assert_equal 2, Abaci.places
|
186
|
+
assert_equal 1, Abaci.things
|
187
|
+
|
188
|
+
Abaci.decrease_things
|
189
|
+
|
190
|
+
assert_equal 0, Abaci.things
|
191
|
+
|
192
|
+
Abaci.clear_people!
|
193
|
+
|
194
|
+
assert_equal 0, Abaci.people
|
195
|
+
|
196
|
+
assert_equal 2, Abaci.last_20_days_of_places
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class DateRangeTest < Test::Unit::TestCase
|
4
|
+
context "The date range calculator" do
|
5
|
+
should "get a day X days in the past" do
|
6
|
+
time = Date.new(2012, 11, 6)
|
7
|
+
expected_time = Date.new(2012, 11, 1)
|
8
|
+
|
9
|
+
Date.stubs(:today).returns(time)
|
10
|
+
|
11
|
+
assert_equal expected_time, Abaci::DateRange.ago(5).start
|
12
|
+
|
13
|
+
Date.unstub(:today)
|
14
|
+
end
|
15
|
+
|
16
|
+
should "get days since a given date" do
|
17
|
+
time = Date.new(2012, 11, 6)
|
18
|
+
expected_time = Date.new(2012, 11, 1)
|
19
|
+
|
20
|
+
Date.stubs(:today).returns(time)
|
21
|
+
|
22
|
+
since = Abaci::DateRange.since(expected_time)
|
23
|
+
|
24
|
+
assert_equal expected_time, since.start
|
25
|
+
assert_equal time, since.finish
|
26
|
+
|
27
|
+
Date.unstub(:today)
|
28
|
+
end
|
29
|
+
|
30
|
+
should "get days between a given date range" do
|
31
|
+
day1 = Date.new(2012, 11, 1)
|
32
|
+
day2 = Date.new(2012, 11, 6)
|
33
|
+
|
34
|
+
range = Abaci::DateRange.between(day1, day2)
|
35
|
+
|
36
|
+
assert_equal day1, range.start
|
37
|
+
assert_equal day2, range.finish
|
38
|
+
end
|
39
|
+
|
40
|
+
should "make days are in order" do
|
41
|
+
day1 = Date.new(2012, 11, 1)
|
42
|
+
day2 = Date.new(2012, 11, 6)
|
43
|
+
|
44
|
+
range = Abaci::DateRange.between(day2, day1)
|
45
|
+
|
46
|
+
assert_equal day1, range.start
|
47
|
+
assert_equal day2, range.finish
|
48
|
+
end
|
49
|
+
|
50
|
+
should "have a range of days" do
|
51
|
+
day1 = Date.new(2012, 11, 1)
|
52
|
+
day2 = Date.new(2012, 11, 6)
|
53
|
+
|
54
|
+
range = Abaci::DateRange.between(day2, day1)
|
55
|
+
|
56
|
+
assert_equal (day1..day2), range.range
|
57
|
+
end
|
58
|
+
|
59
|
+
should "have an array of days" do
|
60
|
+
day1 = Date.new(2012, 11, 1)
|
61
|
+
day2 = Date.new(2012, 11, 6)
|
62
|
+
|
63
|
+
range = Abaci::DateRange.between(day2, day1)
|
64
|
+
|
65
|
+
expected_result = [
|
66
|
+
Date.new(2012, 11, 1),
|
67
|
+
Date.new(2012, 11, 2),
|
68
|
+
Date.new(2012, 11, 3),
|
69
|
+
Date.new(2012, 11, 4),
|
70
|
+
Date.new(2012, 11, 5),
|
71
|
+
Date.new(2012, 11, 6)
|
72
|
+
]
|
73
|
+
|
74
|
+
assert_equal expected_result, range.days
|
75
|
+
end
|
76
|
+
|
77
|
+
should "have a list of store keys for a range" do
|
78
|
+
day1 = Date.new(2012, 11, 1)
|
79
|
+
day2 = Date.new(2012, 11, 6)
|
80
|
+
|
81
|
+
range = Abaci::DateRange.between(day2, day1)
|
82
|
+
|
83
|
+
expected_result = [
|
84
|
+
'2012:11:1',
|
85
|
+
'2012:11:2',
|
86
|
+
'2012:11:3',
|
87
|
+
'2012:11:4',
|
88
|
+
'2012:11:5',
|
89
|
+
'2012:11:6'
|
90
|
+
]
|
91
|
+
|
92
|
+
assert_equal expected_result, range.keys
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# SimpleCov provides test coverage in ruby 1.9 environments only, fail silently
|
2
|
+
# if it is not available
|
3
|
+
begin; require 'simplecov'; rescue LoadError; end
|
4
|
+
|
5
|
+
require 'shoulda'
|
6
|
+
require 'test/unit'
|
7
|
+
require 'mocha'
|
8
|
+
require 'redis'
|
9
|
+
require 'abaci'
|
10
|
+
|
11
|
+
# Fail silently if Turn is not available (runs in 1.9+ only)
|
12
|
+
begin; require 'turn/autorun'; rescue LoadError; end
|
13
|
+
|
14
|
+
REDIS = Redis.new(:db => 1)
|
15
|
+
|
16
|
+
Abaci.redis = REDIS
|
17
|
+
|
18
|
+
class Test::Unit::TestCase
|
19
|
+
def setup
|
20
|
+
REDIS.flushdb
|
21
|
+
Abaci.prefix = 'ab-test'
|
22
|
+
end
|
23
|
+
end
|
data/test/store_test.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class StoreTest < Test::Unit::TestCase
|
4
|
+
context "The abaci store" do
|
5
|
+
should "use a prefix for storage" do
|
6
|
+
Abaci.prefix = 'ab-test'
|
7
|
+
assert_equal 'ab-test', Abaci.prefix
|
8
|
+
|
9
|
+
assert_equal 0, Abaci['prefixes'].get
|
10
|
+
|
11
|
+
assert_equal nil, REDIS.get("ab-test:prefixes")
|
12
|
+
|
13
|
+
Abaci['prefixes'].increment
|
14
|
+
assert_equal 1, Abaci['prefixes'].get
|
15
|
+
|
16
|
+
assert_equal "1", REDIS.get("ab-test:prefixes")
|
17
|
+
end
|
18
|
+
|
19
|
+
should "be able to change the prefix" do
|
20
|
+
Abaci.prefix = 'ab-test-too'
|
21
|
+
|
22
|
+
assert_equal nil, REDIS.get("ab-test:prefixes")
|
23
|
+
assert_equal nil, REDIS.get("ab-test-too:prefixes")
|
24
|
+
|
25
|
+
Abaci.store.set 'prefixes', 1
|
26
|
+
|
27
|
+
assert_equal nil, REDIS.get("ab-test:prefixes")
|
28
|
+
assert_equal "1", REDIS.get("ab-test-too:prefixes")
|
29
|
+
end
|
30
|
+
|
31
|
+
should "list out all keys without prefixes" do
|
32
|
+
now = Time.now
|
33
|
+
|
34
|
+
Abaci['people'].increment
|
35
|
+
|
36
|
+
expected_redis_keys = [
|
37
|
+
'ab-test:people',
|
38
|
+
"ab-test:people:#{now.strftime('%Y')}",
|
39
|
+
"ab-test:people:#{now.strftime('%Y:%-m')}",
|
40
|
+
"ab-test:people:#{now.strftime('%Y:%-m:%-d')}",
|
41
|
+
"ab-test:people:#{now.strftime('%Y:%-m:%-d:%-k')}",
|
42
|
+
"ab-test:people:#{now.strftime('%Y:%-m:%-d:%-k:%-M')}"
|
43
|
+
].sort
|
44
|
+
|
45
|
+
assert_equal expected_redis_keys, REDIS.keys("ab-test:*").sort
|
46
|
+
|
47
|
+
expected_abaci_keys = [
|
48
|
+
'people',
|
49
|
+
"people:#{now.strftime('%Y')}",
|
50
|
+
"people:#{now.strftime('%Y:%-m')}",
|
51
|
+
"people:#{now.strftime('%Y:%-m:%-d')}",
|
52
|
+
"people:#{now.strftime('%Y:%-m:%-d:%-k')}",
|
53
|
+
"people:#{now.strftime('%Y:%-m:%-d:%-k:%-M')}"
|
54
|
+
].sort
|
55
|
+
|
56
|
+
assert_equal expected_abaci_keys, Abaci.store.keys.sort
|
57
|
+
end
|
58
|
+
|
59
|
+
should "be able to delete keys" do
|
60
|
+
Abaci['ipods'].increment
|
61
|
+
|
62
|
+
assert_equal 1, Abaci['ipods'].get
|
63
|
+
|
64
|
+
Abaci.store.del('ipods')
|
65
|
+
|
66
|
+
assert_equal 0, Abaci['ipods'].get
|
67
|
+
end
|
68
|
+
|
69
|
+
should "add list and remove items from a set" do
|
70
|
+
Abaci.store.sadd('_metrics', 'people')
|
71
|
+
Abaci.store.sadd('_metrics', 'places')
|
72
|
+
Abaci.store.sadd('_metrics', 'things')
|
73
|
+
|
74
|
+
assert_equal %w( people places things ).sort, Abaci.store.smembers('_metrics').sort
|
75
|
+
|
76
|
+
Abaci.store.srem('_metrics', 'things')
|
77
|
+
|
78
|
+
assert_equal %w( people places ).sort, Abaci.store.smembers('_metrics').sort
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: abaci
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -35,7 +35,13 @@ executables: []
|
|
35
35
|
extensions: []
|
36
36
|
extra_rdoc_files: []
|
37
37
|
files:
|
38
|
+
- test/counter_test.rb
|
39
|
+
- test/date_range_test.rb
|
40
|
+
- test/helper.rb
|
41
|
+
- test/store_test.rb
|
38
42
|
- lib/abaci/counter.rb
|
43
|
+
- lib/abaci/date_range.rb
|
44
|
+
- lib/abaci/metric.rb
|
39
45
|
- lib/abaci/store.rb
|
40
46
|
- lib/abaci/version.rb
|
41
47
|
- lib/abaci.rb
|