Skip to content

Commit

Permalink
early implementation of "best" counters
Browse files Browse the repository at this point in the history
  • Loading branch information
trvsdnn committed Jan 30, 2013
1 parent 4672dfc commit 8fefeee
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 2 deletions.
1 change: 1 addition & 0 deletions lib/von.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

require 'von/config'
require 'von/counter'
require 'von/best_counter'
require 'von/period'
require 'von/version'

Expand Down
43 changes: 43 additions & 0 deletions lib/von/best_counter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
module Von
class BestCounter

def initialize(parent)
@parent = parent
@field = parent.field
@periods = Von.config.bests[@field]
end

# Returns the Redis hash key used for storing counts for this Counter
def hash_key
@hash_key ||= "#{Von.config.namespace}:counters:bests:#{@field}"
end

def increment
return if @periods.nil?

@periods.each do |period|
# TODO: subclass counter (or somethin) and add hincrby/etc helpers

current_timestamp = Von.connection.hget("#{hash_key}:#{period}:current", 'timestamp')

# TODO: this logic "seems" backwards, rethink current_timestamp
if period.timestamp != current_timestamp
# changing current period
current_total = Von.connection.hget("#{hash_key}:#{period}:current", 'total').to_i
best_total = Von.connection.hget("#{hash_key}:#{period}:best", 'total').to_i

Von.connection.hset("#{hash_key}:#{period}:current", 'total', 1)
Von.connection.hset("#{hash_key}:#{period}:current", 'timestamp', period.timestamp)

if best_total < current_total
Von.connection.hset("#{hash_key}:#{period}:best", 'total', current_total)
Von.connection.hset("#{hash_key}:#{period}:best", 'timestamp', current_timestamp)
end
else
Von.connection.hincrby("#{hash_key}:#{period}:current", 'total', 1)
end
end
end

end
end
2 changes: 2 additions & 0 deletions lib/von/counter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ def hash_key
def increment
total = Von.connection.hincrby(hash_key, 'total', 1)

BestCounter.new(self).increment

increment_periods

total
Expand Down
21 changes: 19 additions & 2 deletions lib/von/period.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ class Period
:monthly => :month,
:yearly => :year
}

TIME_PERIODS = TIME_UNITS.invert

attr_reader :period
attr_reader :counter_key
attr_reader :length
attr_reader :format
Expand All @@ -19,12 +21,16 @@ class Period
# counter - the field name for the counter
# period - the time period one of AVAILABLE_PERIODS
# length - length of period
def initialize(counter_key, period, length)
def initialize(counter_key, period, length = nil)
@counter_key = counter_key
@period = period.to_sym
@length = length
@format = Von.config.send(:"#{@period}_format")
end

def to_s
@period.to_s
end

# Returns a Symbol representing the time unit
# for the current period.
Expand All @@ -37,6 +43,15 @@ def hours?
@period == :hourly
end

def now
# TODO: this may break minutes
DateTime.now.beginning_of_hour
end

def prev
hours? ? now.ago(3600) : now.send(:"prev_#{_period.time_unit}")
end

# Returns the Redis hash key used for storing counts for this Period
def hash_key
@hash ||= "#{Von.config.namespace}:counters:#{@counter_key}:#{@period}"
Expand All @@ -48,9 +63,11 @@ def list_key
end

# Returns the Redis field representation used for storing the count value
# TODO: rename this
def field
Time.now.strftime(format)
end
alias :timestamp :field

def self.exists?(period)
AVAILABLE_PERIODS.include?(period)
Expand Down
31 changes: 31 additions & 0 deletions test/best_counter_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
require 'test_helper'

describe Von::BestCounter do
Counter = Von::BestCounter

before :each do
Timecop.freeze(Time.local(2013, 01, 01))
Von.config.init!
@redis = Redis.new
@redis.flushall
end

it "increments the best counter for a period" do
Von.configure do |config|
config.counter 'foo', :best => :day
end

Counter.increment('foo')

Timecop.freeze(Time.local(2013, 01, 02))
10.times { Counter.increment('foo') }
Timecop.freeze(Time.local(2013, 01, 03))
3.times { Counter.increment('foo') }

@redis.hget('von:counters:bests:foo:daily:current', 'timestamp').must_equal '2013-01-03'
@redis.hget('von:counters:bests:foo:daily:current', 'total').must_equal '3'
@redis.hget('von:counters:bests:foo:daily:best', 'timestamp').must_equal '2013-01-02'
@redis.hget('von:counters:bests:foo:daily:best', 'total').must_equal '10'
end

end

0 comments on commit 8fefeee

Please sign in to comment.