class Redis::Counter

Class representing a Redis counter. This functions like a proxy class, in that you can say @object.counter_name to get the value and then @object.counter_name.increment to operate on it. You can use this directly, or you can use the counter :foo class method in your class to define a counter.

Public Class Methods

new(key, *args) click to toggle source
Calls superclass method Redis::BaseObject::new
# File lib/redis/counter.rb, line 12
def initialize(key, *args)
  super(key, *args)
  @options[:start] ||= @options[:default] || 0
  raise ArgumentError, "Marshalling redis counters does not make sense" if @options[:marshal]
  redis.setnx(key, @options[:start]) unless @options[:start] == 0 || @options[:init] === false
end

Public Instance Methods

decr(by=1, &block)
Alias for: decrement
decrby(by=1, &block)
Alias for: decrement
decrbyfloat(by=1.0, &block) click to toggle source

Decrement a floating point counter atomically. Redis uses separate API’s to interact with integers vs floats.

# File lib/redis/counter.rb, line 102
def decrbyfloat(by=1.0, &block)
  allow_expiration do
    val = redis.incrbyfloat(key, -by).to_f
    block_given? ? rewindable_block(:incrbyfloat, by, val, &block) : val
  end
end
decrement(by=1, &block) click to toggle source

Decrement the counter atomically and return the new value. If passed a block, that block will be evaluated with the new value of the counter as an argument. If the block returns nil or throws an exception, the counter will automatically be incremented to its previous value. This method is aliased as decr() for brevity.

# File lib/redis/counter.rb, line 82
def decrement(by=1, &block)
  allow_expiration do
    val = redis.decrby(key, by).to_i
    block_given? ? rewindable_block(:increment, by, val, &block) : val
  end
end
Also aliased as: decr, decrby
get()
Alias for: value
getset(to=options[:start]) click to toggle source

Reset the counter to its starting value, and return previous value. Use this to “reap” the counter and save it somewhere else. This is atomic in that no increments or decrements are lost if you process the returned value.

# File lib/redis/counter.rb, line 34
def getset(to=options[:start])
  redis.getset(key, to.to_i).to_i
end
incr(by=1, &block)
Alias for: increment
incrby(by=1, &block)
Alias for: increment
incrbyfloat(by=1.0, &block) click to toggle source

Increment a floating point counter atomically. Redis uses separate API’s to interact with integers vs floats.

# File lib/redis/counter.rb, line 93
def incrbyfloat(by=1.0, &block)
  allow_expiration do
    val = redis.incrbyfloat(key, by).to_f
    block_given? ? rewindable_block(:decrbyfloat, by, val, &block) : val
  end
end
increment(by=1, &block) click to toggle source

Increment the counter atomically and return the new value. If passed a block, that block will be evaluated with the new value of the counter as an argument. If the block returns nil or throws an exception, the counter will automatically be decremented to its previous value. This method is aliased as incr() for brevity.

# File lib/redis/counter.rb, line 68
def increment(by=1, &block)
  allow_expiration do
    val = redis.incrby(key, by).to_i
    block_given? ? rewindable_block(:decrement, by, val, &block) : val
  end
end
Also aliased as: incr, incrby
nil?() click to toggle source
# File lib/redis/counter.rb, line 114
def nil?
  !redis.exists?(key)
end
reset(to=options[:start]) click to toggle source

Reset the counter to its starting value. Not atomic, so use with care. Normally only useful if you’re discarding all sub-records associated with a parent and starting over (for example, restarting a game and disconnecting all players).

# File lib/redis/counter.rb, line 23
def reset(to=options[:start])
  allow_expiration do
    redis.set key, to.to_i
    true  # hack for redis-rb regression
  end
end
set(val)
Alias for: value=
to_f() click to toggle source

Like .value but casts to float since Redis addresses these differently.

# File lib/redis/counter.rb, line 59
def to_f
  redis.get(key).to_f
end
to_i()
Alias for: value
to_s() click to toggle source

Proxy methods to help make @object.counter == 10 work

# File lib/redis/counter.rb, line 111
def to_s; value.to_s; end
value() click to toggle source

Returns the current value of the counter. Normally just calling the counter will lazily fetch the value, and only update it if increment or decrement is called. This forces a network call to redis-server to get the current value.

# File lib/redis/counter.rb, line 42
def value
  redis.get(key).to_i
end
Also aliased as: get, to_i
value=(val) click to toggle source
# File lib/redis/counter.rb, line 47
def value=(val)
  allow_expiration do
    if val.nil?
      delete
    else
      redis.set key, val
    end
  end
end
Also aliased as: set

Private Instance Methods

rewindable_block(rewind, by, value) { |value| ... } click to toggle source

Implements atomic increment/decrement blocks

# File lib/redis/counter.rb, line 132
def rewindable_block(rewind, by, value, &block)
  raise ArgumentError, "Missing block to rewindable_block somehow" unless block_given?
  ret = nil
  begin
    ret = yield value
  rescue
    send(rewind, by)
    raise
  end
  send(rewind, by) if ret.nil?
  ret
end