class TrafficJam::LifetimeLimit

This class represents a lifetime limit on an action, value pair. For example, if limiting the amount of money a user can transfer, the action could be :transfers and the value would be the user ID. The class exposes atomic increment operations and allows querying of the current amount used and amount remaining.

Public Class Methods

new(action, value, max: nil) click to toggle source

Constructor takes an action name as a symbol, a maximum cap, and the period of limit. max and period are required keyword arguments.

@param action [Symbol] action name @param value [String] limit target value @param max [Integer] required limit maximum @raise [ArgumentError] if max is nil

Calls superclass method
# File lib/traffic_jam/lifetime_limit.rb, line 15
def initialize(action, value, max: nil)
  super(action, value, max: max, period: -1)
end

Public Instance Methods

increment(amount = 1, time: Time.now) click to toggle source

Increment the amount used by the given number. Does not perform increment if the operation would exceed the limit. Returns whether the operation was successful.

@param amount [Integer] amount to increment by @return [Boolean] true if increment succeded and false if incrementing

would exceed the limit
# File lib/traffic_jam/lifetime_limit.rb, line 26
def increment(amount = 1, time: Time.now)
  raise ArgumentError, 'Amount must be an integer' if amount != amount.to_i
  return amount <= 0 if max.zero?

  !!run_script([amount.to_i, max])
end
used() click to toggle source

Return amount of limit used

@return [Integer] amount used

# File lib/traffic_jam/lifetime_limit.rb, line 36
def used
  return 0 if max.zero?
  amount = redis.get(key) || 0
  [amount.to_i, max].min
end

Private Instance Methods

run_script(argv) click to toggle source
# File lib/traffic_jam/lifetime_limit.rb, line 44
def run_script(argv)
  redis.evalsha(
    Scripts::INCRBY_HASH, keys: [key], argv: argv
  )
rescue Redis::CommandError => error
  raise error if /ERR Error running script/ =~ error.message
  redis.eval(Scripts::INCRBY, keys: [key], argv: argv)
end