Browse files

counter instance for dispatching count queries, support for bests clo…

…ses #1
  • Loading branch information...
1 parent 853cf87 commit 6c852f1e4844927ee02125b7fd3b45f41888c593 @blahed committed Jan 30, 2013
Showing with 139 additions and 20 deletions.
  1. +6 −8 lib/von.rb
  2. +1 −0 lib/von/config.rb
  3. +53 −0 lib/von/counter.rb
  4. +8 −3 lib/von/counters/best.rb
  5. +4 −0 lib/von/period.rb
  6. +56 −0 test/counter_test.rb
  7. +11 −9 test/von_test.rb
View
14 lib/von.rb
@@ -3,6 +3,7 @@
require 'von/config'
require 'von/period'
+require 'von/counter'
require 'von/counters/total'
require 'von/counters/period'
require 'von/counters/best'
@@ -44,21 +45,18 @@ def self.increment_counts_for(field)
if config.periods_defined_for_counter?(counter)
periods = config.periods[counter.field]
Counters::Period.new(counter.field, periods).increment
- elsif config.bests_defined_for_counter?(counter)
+ end
+
+ if config.bests_defined_for_counter?(counter)
periods = config.bests[counter.field]
Counters::Best.new(counter.field, periods).increment
end
total
end
- def self.count(field, period = nil)
- if period.nil?
- Counters::Total.new(field).count
- else
- periods = config.periods[field.to_sym]
- Counters::Period.new(field, periods).count(period)
- end
+ def self.count(field)
+ Counter.new(field)
rescue Redis::BaseError => e
raise e if config.raise_connection_errors
end
View
1 lib/von/config.rb
@@ -68,6 +68,7 @@ def counter(field, options = {})
# Returns a True if a period is defined for the
# given Counter
+ # TODO: these should just take the key, will fix when renaming field
def periods_defined_for_counter?(counter)
@periods.has_key?(counter.field)
end
View
53 lib/von/counter.rb
@@ -0,0 +1,53 @@
+module Von
+ class Counter
+
+ def initialize(field)
+ @field = field.to_sym
+ end
+
+ def to_s
+ Counters::Total.new(@field).count.to_s
+ rescue Redis::BaseError => e
+ raise e if Von.config.raise_connection_errors
+ end
+
+ def to_i
+ Counters::Total.new(@field).count
+ rescue Redis::BaseError => e
+ raise e if Von.config.raise_connection_errors
+ end
+
+ def total
+ Counters::Total.new(@field).count
+ rescue Redis::BaseError => e
+ raise e if Von.config.raise_connection_errors
+ end
+
+ def per(unit)
+ periods = Von.config.periods[@field]
+ period = Period.unit_to_period(unit)
+
+ if period.nil?
+ raise ArgumentError, "`#{unit}' is an unknown time unit"
+ else
+ Counters::Period.new(@field, periods).count(period)
+ end
+ rescue Redis::BaseError => e
+ raise e if Von.config.raise_connection_errors
+ end
+
+ def best(unit)
+ periods = Von.config.bests[@field]
+ period = Period.unit_to_period(unit)
+
+ if period.nil?
+ raise ArgumentError, "`#{unit}' is an unknown time unit"
+ else
+ Counters::Best.new(@field, periods).count(period)
+ end
+ rescue Redis::BaseError => e
+ raise e if Von.config.raise_connection_errors
+ end
+
+ end
+end
View
11 lib/von/counters/best.rb
@@ -51,10 +51,15 @@ def increment
end
def count(period)
- if current_timestamp > best_timestamp
- { current_timestamp => current_total }
+ _current_timestamp = current_timestamp(period)
+ _current_total = current_total(period)
+ _best_timestamp = best_timestamp(period)
+ _best_total = best_total(period)
+
+ if _current_total > _best_total
+ { _current_timestamp => _current_total }
else
- { best_timestamp => best_total }
+ { _best_timestamp => _best_total }
end
end
View
4 lib/von/period.rb
@@ -68,6 +68,10 @@ def prev(unit = 1)
def timestamp
beginning(Time.now).strftime(format)
end
+
+ def self.unit_to_period(time_unit)
+ PERIOD_MAPPING.invert[time_unit]
+ end
def self.exists?(period)
AVAILABLE_PERIODS.include?(period)
View
56 test/counter_test.rb
@@ -0,0 +1,56 @@
+require 'test_helper'
+
+describe Von::Counter do
+ Counter = Von::Counter
+
+ before :each do
+ Timecop.freeze(Time.local(2013, 01, 01, 01, 01))
+ Von.config.init!
+ @redis = Redis.new
+ @redis.flushall
+ end
+
+ it "returns count for key" do
+ 3.times { Von.increment('foo') }
+ Counter.new('foo').total.must_equal 3
+ end
+
+ it "returns count for key and parent keys" do
+ 3.times { Von.increment('foo:bar') }
+ Counter.new('foo').total.must_equal 3
+ Counter.new('foo:bar').total.must_equal 3
+ end
+
+
+ it "returns counts for a given period" do
+ Von.configure do |config|
+ config.counter 'foo', :monthly => 2
+ end
+
+ Von.increment('foo')
+ Timecop.freeze(Time.local(2013, 02))
+ Von.increment('foo')
+ Timecop.freeze(Time.local(2013, 03))
+ Von.increment('foo')
+
+ Counter.new('foo').per(:month).must_equal [{ "2013-02" => 1 }, { "2013-03" => 1 }]
+ end
+
+ it "returns best count for a given period" do
+ Von.configure do |config|
+ config.counter 'foo', :best => [:minute, :week]
+ end
+
+ Von.increment('foo')
+
+ Timecop.freeze(Time.local(2013, 01, 13, 06, 05))
+ 4.times { Von.increment('foo') }
+ Timecop.freeze(Time.local(2013, 01, 20, 06, 10))
+ 3.times { Von.increment('foo') }
+
+ Counter.new('foo').best(:minute).must_equal({ "2013-01-13 06:05" => 4 })
+ Counter.new('foo').best(:week).must_equal({ "2013-01-07" => 4 })
+ end
+
+
+end
View
20 test/von_test.rb
@@ -11,27 +11,29 @@
it "increments a counter and counts it" do
3.times { Von.increment('foo') }
- Von.count('foo').must_equal 3
+ Von.count('foo').total.must_equal 3
end
-
+
it "increments a counter and parent counters and counts them" do
3.times { Von.increment('foo:bar') }
- Von.count('foo').must_equal 3
- Von.count('foo:bar').must_equal 3
+ Von.count('foo').total.must_equal 3
+ Von.count('foo:bar').total.must_equal 3
end
- it "increments period counters and counts them" do
+ it "increments period/best counters and counts them" do
Von.configure do |config|
- config.counter 'foo', :monthly => 2
+ config.counter 'foo', :monthly => 2, :best => :day
end
Von.increment('foo')
- Timecop.freeze(Time.local(2013, 02))
+ Timecop.freeze(Time.local(2013, 02, 03))
+ Von.increment('foo')
Von.increment('foo')
- Timecop.freeze(Time.local(2013, 03))
+ Timecop.freeze(Time.local(2013, 03, 04))
Von.increment('foo')
- Von.count('foo', :monthly).must_equal [{"2013-02"=>1}, {"2013-03"=>1}]
+ Von.count('foo').best(:day).must_equal({ "2013-02-03" => 2 })
+ Von.count('foo').per(:month).must_equal [{ "2013-02" => 2 }, { "2013-03" => 1 }]
end
it "raises a Redis connection errors if raise_connection_errors is true" do

0 comments on commit 6c852f1

Please sign in to comment.