Skip to content

Commit

Permalink
counter instance for dispatching count queries, support for bests closes
Browse files Browse the repository at this point in the history
  • Loading branch information
trvsdnn committed Jan 30, 2013
1 parent 853cf87 commit 6c852f1
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 20 deletions.
14 changes: 6 additions & 8 deletions lib/von.rb
Expand Up @@ -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'
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions lib/von/config.rb
Expand Up @@ -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
Expand Down
53 changes: 53 additions & 0 deletions 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
11 changes: 8 additions & 3 deletions lib/von/counters/best.rb
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions lib/von/period.rb
Expand Up @@ -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)
Expand Down
56 changes: 56 additions & 0 deletions 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
20 changes: 11 additions & 9 deletions test/von_test.rb
Expand Up @@ -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
Expand Down

0 comments on commit 6c852f1

Please sign in to comment.