Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

early implementation of "best" counters

  • Loading branch information...
commit 8fefeee5492c2ce2d5a5bebe1462a714f32d8107 1 parent 4672dfc
Travis Dunn authored
1  lib/von.rb
View
@@ -3,6 +3,7 @@
require 'von/config'
require 'von/counter'
+require 'von/best_counter'
require 'von/period'
require 'von/version'
43 lib/von/best_counter.rb
View
@@ -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  lib/von/counter.rb
View
@@ -23,6 +23,8 @@ def hash_key
def increment
total = Von.connection.hincrby(hash_key, 'total', 1)
+ BestCounter.new(self).increment
+
increment_periods
total
21 lib/von/period.rb
View
@@ -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
@@ -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.
@@ -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}"
@@ -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)
31 test/best_counter_test.rb
View
@@ -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
Please sign in to comment.
Something went wrong with that request. Please try again.