Skip to content

Commit

Permalink
Allow to increment counters by given value
Browse files Browse the repository at this point in the history
  • Loading branch information
jakubkosinski committed Nov 30, 2013
1 parent d4c39b2 commit fdce256
Show file tree
Hide file tree
Showing 10 changed files with 59 additions and 48 deletions.
16 changes: 8 additions & 8 deletions lib/von.rb
Expand Up @@ -26,12 +26,12 @@ def self.configure
yield(config)
end

def self.increment(field)
def self.increment(field, by=1)
parents = field.to_s.sub(PARENT_REGEX, '')
total = increment_counts_for(field)
total = increment_counts_for(field, by)

until parents.empty? do
increment_counts_for(parents)
increment_counts_for(parents, by)
parents.sub!(PARENT_REGEX, '')
end

Expand All @@ -40,23 +40,23 @@ def self.increment(field)
raise e if config.raise_connection_errors
end

def self.increment_counts_for(field)
def self.increment_counts_for(field, by=1)
counter = Counters::Total.new(field)
total = counter.increment
total = counter.increment(by)

if config.periods_defined_for_counter?(counter)
periods = config.periods[counter.field]
Counters::Period.new(counter.field, periods).increment
Counters::Period.new(counter.field, periods).increment(by)
end

if config.bests_defined_for_counter?(counter)
periods = config.bests[counter.field]
Counters::Best.new(counter.field, periods).increment
Counters::Best.new(counter.field, periods).increment(by)
end

if config.currents_defined_for_counter?(counter)
periods = config.currents[counter.field]
Counters::Current.new(counter.field, periods).increment
Counters::Current.new(counter.field, periods).increment(by)
end

total
Expand Down
8 changes: 4 additions & 4 deletions lib/von/counters/best.rb
Expand Up @@ -28,7 +28,7 @@ def current_timestamp(time_unit)
hget("#{hash_key}:#{time_unit}:current", 'timestamp')
end

def increment
def increment(by=1)
return if @periods.empty?

@periods.each do |period|
Expand All @@ -37,15 +37,15 @@ def increment

if period.timestamp != _current_timestamp
# changing current period
hset("#{hash_key}:#{period.time_unit}:current", 'total', 1)
hset("#{hash_key}:#{period.time_unit}:current", 'total', by)
hset("#{hash_key}:#{period.time_unit}:current", 'timestamp', period.timestamp)

if best_total(period) < _current_total
hset("#{hash_key}:#{period.time_unit}:best", 'total', _current_total)
hset("#{hash_key}:#{period.time_unit}:best", 'timestamp', _current_timestamp)
end
else
hincrby("#{hash_key}:#{period.time_unit}:current", 'total', 1)
hincrby("#{hash_key}:#{period.time_unit}:current", 'total', by)
end
end
end
Expand All @@ -65,4 +65,4 @@ def count(time_unit)

end
end
end
end
6 changes: 3 additions & 3 deletions lib/von/counters/current.rb
Expand Up @@ -20,15 +20,15 @@ def current_timestamp(time_unit)
hget("#{hash_key}:#{time_unit}", 'timestamp')
end

def increment
def increment(by=1)
return if @periods.empty?

@periods.each do |period|
if period.timestamp != current_timestamp(period.time_unit)
hset("#{hash_key}:#{period.time_unit}", 'total', 1)
hset("#{hash_key}:#{period.time_unit}", 'total', by)
hset("#{hash_key}:#{period.time_unit}", 'timestamp', period.timestamp)
else
hincrby("#{hash_key}:#{period.time_unit}", 'total', 1)
hincrby("#{hash_key}:#{period.time_unit}", 'total', by)
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions lib/von/counters/period.rb
Expand Up @@ -18,14 +18,14 @@ def list_key(time_unit)
"#{Von.config.namespace}:lists:#{@field}:#{time_unit}"
end

def increment
def increment(by=1)
return if @periods.empty?

@periods.each do |period|
_hash_key = hash_key(period.time_unit)
_list_key = list_key(period.time_unit)

hincrby(_hash_key, period.timestamp, 1)
hincrby(_hash_key, period.timestamp, by)

unless lrange(_list_key, 0, -1).include?(period.timestamp)
rpush(_list_key, period.timestamp)
Expand Down
4 changes: 2 additions & 2 deletions lib/von/counters/total.rb
Expand Up @@ -21,8 +21,8 @@ def hash_key
# If the key has time periods specified, increment those.
#
# Returns the Integer total for the key
def increment
hincrby(hash_key, 'total', 1).to_i
def increment(by=1)
hincrby(hash_key, 'total', by).to_i
end

# Count the "total" field for this Counter.
Expand Down
10 changes: 5 additions & 5 deletions test/counters/best_test.rb
Expand Up @@ -16,14 +16,14 @@
counter.increment

Timecop.freeze(Time.local(2013, 01, 02))
4.times { counter.increment }
4.times { counter.increment(2) }
Timecop.freeze(Time.local(2013, 01, 03))
3.times { counter.increment }

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

it "increments the best counter for multiple periods" do
Expand All @@ -35,19 +35,19 @@
counter.increment

Timecop.freeze(Time.local(2013, 01, 13, 06, 05))
4.times { counter.increment }
4.times { counter.increment(2) }
Timecop.freeze(Time.local(2013, 01, 20, 06, 10))
3.times { counter.increment }

@redis.hget('von:counters:bests:foo:minute:current', 'timestamp').must_equal '2013-01-20 06:10'
@redis.hget('von:counters:bests:foo:minute:current', 'total').must_equal '3'
@redis.hget('von:counters:bests:foo:minute:best', 'timestamp').must_equal '2013-01-13 06:05'
@redis.hget('von:counters:bests:foo:minute:best', 'total').must_equal '4'
@redis.hget('von:counters:bests:foo:minute:best', 'total').must_equal '8'

@redis.hget('von:counters:bests:foo:week:current', 'timestamp').must_equal '2013-01-14'
@redis.hget('von:counters:bests:foo:week:current', 'total').must_equal '3'
@redis.hget('von:counters:bests:foo:week:best', 'timestamp').must_equal '2013-01-07'
@redis.hget('von:counters:bests:foo:week:best', 'total').must_equal '4'
@redis.hget('von:counters:bests:foo:week:best', 'total').must_equal '8'
end

end
16 changes: 8 additions & 8 deletions test/counters/current_test.rb
Expand Up @@ -15,10 +15,10 @@

4.times { counter.increment }
Timecop.freeze(Time.local(2013, 01, 02))
3.times { counter.increment }
3.times { counter.increment(2) }

@redis.hget('von:counters:currents:foo:day', 'timestamp').must_equal '2013-01-02'
@redis.hget('von:counters:currents:foo:day', 'total').must_equal '3'
@redis.hget('von:counters:currents:foo:day', 'total').must_equal '6'
end

it "increments the current counter for multiple periods" do
Expand All @@ -29,13 +29,13 @@

4.times { counter.increment }
Timecop.freeze(Time.local(2013, 01, 20, 06, 10))
3.times { counter.increment }
3.times { counter.increment(2) }

@redis.hget('von:counters:currents:foo:minute', 'timestamp').must_equal '2013-01-20 06:10'
@redis.hget('von:counters:currents:foo:minute', 'total').must_equal '3'
@redis.hget('von:counters:currents:foo:minute', 'total').must_equal '6'

@redis.hget('von:counters:currents:foo:week', 'timestamp').must_equal '2013-01-14'
@redis.hget('von:counters:currents:foo:week', 'total').must_equal '3'
@redis.hget('von:counters:currents:foo:week', 'total').must_equal '6'
end

it "counts acurrent counter for a period" do
Expand All @@ -46,10 +46,10 @@

4.times { counter.increment }
Timecop.freeze(Time.local(2013, 01, 01, 06, 10))
3.times { counter.increment }
3.times { counter.increment(2) }

counter.count(:minute).must_equal 3
counter.count(:day).must_equal 7
counter.count(:minute).must_equal 6
counter.count(:day).must_equal 10
end

end
18 changes: 9 additions & 9 deletions test/counters/period_test.rb
Expand Up @@ -16,9 +16,9 @@
])

counter.increment
counter.increment
counter.increment(5)

@redis.hget('von:counters:foo:month', '2013-01').must_equal '2'
@redis.hget('von:counters:foo:month', '2013-01').must_equal '6'
@redis.lrange('von:lists:foo:month', 0, -1).size.must_equal 1
@redis.lrange('von:lists:foo:month', 0, -1).first.must_equal '2013-01'
end
Expand All @@ -29,9 +29,9 @@
])

counter.increment
counter.increment
counter.increment(5)

@redis.hget('von:counters:foo:minute', '2013-01-01 01:01').must_equal '2'
@redis.hget('von:counters:foo:minute', '2013-01-01 01:01').must_equal '6'
@redis.lrange('von:lists:foo:minute', 0, -1).size.must_equal 1
@redis.lrange('von:lists:foo:minute', 0, -1).first.must_equal '2013-01-01 01:01'
end
Expand All @@ -43,9 +43,9 @@

counter.increment
Timecop.freeze(Time.local(2013, 02))
counter.increment
counter.increment(5)

@redis.hget('von:counters:foo:month', '2013-02').must_equal '1'
@redis.hget('von:counters:foo:month', '2013-02').must_equal '5'
@redis.lrange('von:lists:foo:month', 0, -1).size.must_equal 1
@redis.lrange('von:lists:foo:month', 0, -1).first.must_equal '2013-02'
end
Expand All @@ -60,16 +60,16 @@
counter.increment
counter.increment
Timecop.freeze(Time.local(2013, 02, 01, 7))
counter.increment
counter.increment(5)
Timecop.freeze(Time.local(2013, 02, 01, 9))
counter.increment

counter.count(:month).must_equal [{ timestamp: "2013-02", count: 2 }]
counter.count(:month).must_equal [{ timestamp: "2013-02", count: 6 }]
counter.count(:hour).must_equal [
{ timestamp: "2013-02-01 04:00", count: 0 },
{ timestamp: "2013-02-01 05:00", count: 0 },
{ timestamp: "2013-02-01 06:00", count: 0 },
{ timestamp: "2013-02-01 07:00", count: 1 },
{ timestamp: "2013-02-01 07:00", count: 5 },
{ timestamp: "2013-02-01 08:00", count: 0 },
{ timestamp: "2013-02-01 09:00", count: 1 }
]
Expand Down
8 changes: 4 additions & 4 deletions test/counters/total_test.rb
Expand Up @@ -16,17 +16,17 @@
counter.increment
@redis.hget('von:counters:foo', 'total').must_equal '1'

counter.increment
@redis.hget('von:counters:foo', 'total').must_equal '2'
counter.increment(5)
@redis.hget('von:counters:foo', 'total').must_equal '6'
end

it "gets a total count for a counter" do
counter = TotalCounter.new('foo')
counter.increment
counter.increment
counter.increment(3)
counter.increment

counter.count.must_equal 3
counter.count.must_equal 5
end


Expand Down
17 changes: 14 additions & 3 deletions test/von_test.rb
Expand Up @@ -14,12 +14,23 @@
Von.count('foo').total.must_equal 3
end

it "increments a counter by given value and counts it" do
3.times { Von.increment('foo', 5) }
Von.count('foo').total.must_equal 15
end

it "increments a counter and parent counters and counts them" do
3.times { Von.increment('foo:bar') }
Von.count('foo').total.must_equal 3
Von.count('foo:bar').total.must_equal 3
end

it "increments a counter and parent counters by given value and counts them" do
3.times { Von.increment('foo:bar', 5) }
Von.count('foo').total.must_equal 15
Von.count('foo:bar').total.must_equal 15
end

it "increments period/best counters and counts them" do
Von.configure do |config|
config.counter 'foo', monthly: 2, best: :day
Expand All @@ -28,12 +39,12 @@
Von.increment('foo')
Timecop.freeze(Time.local(2013, 02, 03))
Von.increment('foo')
Von.increment('foo')
Von.increment('foo', 2)
Timecop.freeze(Time.local(2013, 03, 04))
Von.increment('foo')

Von.count('foo').best(:day).must_equal({ timestamp: "2013-02-03", count: 2 })
Von.count('foo').per(:month).must_equal [{ timestamp: "2013-02", count: 2 }, { timestamp: "2013-03", count: 1 }]
Von.count('foo').best(:day).must_equal({ timestamp: "2013-02-03", count: 3 })
Von.count('foo').per(:month).must_equal [{ timestamp: "2013-02", count: 3 }, { timestamp: "2013-03", count: 1 }]
end

it "raises a Redis connection errors if raise_connection_errors is true" do
Expand Down

0 comments on commit fdce256

Please sign in to comment.