Class: TrafficJam::LimitGroup

Inherits:
Object
  • Object
show all
Defined in:
lib/traffic_jam/limit_group.rb

Overview

A limit group is a way of enforcing a cap over a set of limits with the guarantee that either all limits will be incremented or none. This is useful if you must check multiple limits before allowing an action to be taken. Limit groups can contain other limit groups.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*limits, ignore_nil_values: false) ⇒ LimitGroup

Creates a limit group from a collection of limits or other limit groups.

Parameters:

  • limits (Array<TrafficJam::Limit>)

    either an array or splat of limits or other limit groups

  • ignore_nil_values (Boolean) (defaults to: false)

    silently drop limits with a nil value



14
15
16
17
18
19
20
21
22
# File 'lib/traffic_jam/limit_group.rb', line 14

def initialize(*limits, ignore_nil_values: false)
  @limits = limits.flatten
  @ignore_nil_values = ignore_nil_values
  if @ignore_nil_values
    @limits.reject! do |limit|
      limit.respond_to?(:value) && limit.value.nil?
    end
  end
end

Instance Attribute Details

#limitsObject (readonly)

Returns the value of attribute limits.



7
8
9
# File 'lib/traffic_jam/limit_group.rb', line 7

def limits
  @limits
end

Instance Method Details

#<<(limit) ⇒ Object

Add a limit to the group.



27
28
29
30
31
# File 'lib/traffic_jam/limit_group.rb', line 27

def <<(limit)
  if !(@ignore_nil_values && limit.value.nil?)
    limits << limit
  end
end

#decrement(amount = 1, time: Time.now) ⇒ true

Decrement the limits by the given amount.

Parameters:

  • amount (Integer) (defaults to: 1)

    amount to decrement by

  • time (Time) (defaults to: Time.now)

    optional time of decrement

Returns:

  • (true)


82
83
84
# File 'lib/traffic_jam/limit_group.rb', line 82

def decrement(amount = 1, time: Time.now)
  limits.all? { |limit| limit.decrement(amount, time: time) }
end

#exceeded?(amount = 1) ⇒ Boolean

Return whether incrementing by the given amount would exceed any limit. Does not change amount used.

Parameters:

  • amount (Integer) (defaults to: 1)

Returns:

  • (Boolean)

    whether any limit would be exceeded



91
92
93
# File 'lib/traffic_jam/limit_group.rb', line 91

def exceeded?(amount = 1)
  limits.any? { |limit| limit.exceeded?(amount) }
end

#flattenArray<TrafficJam::Limit>

Return flattened list of limit. Will return list limits even if this group contains nested limit groups.

Returns:



125
126
127
# File 'lib/traffic_jam/limit_group.rb', line 125

def flatten
  limits.map(&:flatten).flatten
end

#increment(amount = 1, time: Time.now) ⇒ Boolean

Attempt to increment the limits by the given amount. Does not increment if incrementing would exceed any limit.

Parameters:

  • amount (Integer) (defaults to: 1)

    amount to increment by

  • time (Time) (defaults to: Time.now)

    optional time of increment

Returns:

  • (Boolean)

    whether increment operation was successful



39
40
41
42
43
44
45
46
47
48
49
# File 'lib/traffic_jam/limit_group.rb', line 39

def increment(amount = 1, time: Time.now)
  exceeded_index = limits.find_index do |limit|
    !limit.increment(amount, time: time)
  end
  if exceeded_index
    limits[0...exceeded_index].each do |limit|
      limit.decrement(amount, time: time)
    end
  end
  exceeded_index.nil?
end

#increment!(amount = 1, time: Time.now) ⇒ nil

Increment the limits by the given amount. Raises an error and does not increment if doing so would exceed any limit.

Parameters:

  • amount (Integer) (defaults to: 1)

    amount to increment by

  • time (Time) (defaults to: Time.now)

    optional time of increment

Returns:

  • (nil)

Raises:



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/traffic_jam/limit_group.rb', line 59

def increment!(amount = 1, time: Time.now)
  exception = nil
  exceeded_index = limits.find_index do |limit|
    begin
      limit.increment!(amount, time: time)
    rescue TrafficJam::LimitExceededError => e
      exception = e
      true
    end
  end
  if exceeded_index
    limits[0...exceeded_index].each do |limit|
      limit.decrement(amount, time: time)
    end
    raise exception
  end
end

#limit_exceeded(amount = 1) ⇒ TrafficJam::Limit?

Return the first limit to be exceeded if incrementing by the given amount, or nil otherwise. Does not change amount used for any limit.

Parameters:

  • amount (Integer) (defaults to: 1)

Returns:



100
101
102
103
104
105
106
# File 'lib/traffic_jam/limit_group.rb', line 100

def limit_exceeded(amount = 1)
  limits.each do |limit|
    limit_exceeded = limit.limit_exceeded(amount)
    return limit_exceeded if limit_exceeded
  end
  nil
end

#remainingInteger

Return minimum amount remaining of any limit.

Returns:

  • (Integer)

    amount remaining in limit group



117
118
119
# File 'lib/traffic_jam/limit_group.rb', line 117

def remaining
  limits.map(&:remaining).min
end

#resetObject

Resets all limits to 0.



109
110
111
112
# File 'lib/traffic_jam/limit_group.rb', line 109

def reset
  limits.each(&:reset)
  nil
end