Class: CMDx::RateLimit
- Inherits:
-
Object
- Object
- CMDx::RateLimit
- Defined in:
- lib/cmdx/rate_limit.rb
Overview
Declared via Task.rate_limit. After inputs resolve, consults a shared limiter once per execution (retries do not consume additional quota) and short-circuits before the circuit breaker when the bucket is full.
Store keys come from StoreKey#task_key with class_scoped: true — either
namespace:TaskName for {StoreKey::CLASS_KEY} (:class) or
namespace:TaskName:segment when a resolver yields a segment.
Defined Under Namespace
Instance Attribute Summary collapse
-
#key ⇒ Object
readonly
Returns the value of attribute key.
Class Method Summary collapse
-
.disabled ⇒ RateLimit
Disabled configuration (no key).
Instance Method Summary collapse
-
#build(new_key, new_options) ⇒ RateLimit
Returns a new RateLimit layering
new_optionsonto the current one. - #condition_if ⇒ Symbol, ...
- #condition_unless ⇒ Symbol, ...
- #cost ⇒ Numeric
- #enabled? ⇒ Boolean
-
#initialize(key, options = EMPTY_HASH) ⇒ RateLimit
constructor
A new instance of RateLimit.
- #limiter ⇒ Symbol
- #max ⇒ Integer?
- #namespace ⇒ String
-
#on_limit ⇒ Symbol
:failor:skip. - #per ⇒ Integer?
-
#process(task) { ... } ⇒ Object
Runs the limiter once, then yields when admitted or inactive.
Constructor Details
#initialize(key, options = EMPTY_HASH) ⇒ RateLimit
Returns a new instance of RateLimit.
65 66 67 68 |
# File 'lib/cmdx/rate_limit.rb', line 65 def initialize(key, = EMPTY_HASH) @key = key @options = .freeze end |
Instance Attribute Details
#key ⇒ Object (readonly)
Returns the value of attribute key.
51 52 53 |
# File 'lib/cmdx/rate_limit.rb', line 51 def key @key end |
Class Method Details
.disabled ⇒ RateLimit
Returns disabled configuration (no key).
45 46 47 |
# File 'lib/cmdx/rate_limit.rb', line 45 def disabled DISABLED end |
Instance Method Details
#build(new_key, new_options) ⇒ RateLimit
Returns a new RateLimit layering new_options onto the current one.
123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/cmdx/rate_limit.rb', line 123 def build(new_key, ) return self if new_key.nil? && .empty? merged_key = if new_key.nil? enabled? || .empty? ? @key : StoreKey::CLASS_KEY else new_key end = @options.merge() self.class.new(merged_key, ) end |
#condition_if ⇒ Symbol, ...
104 105 106 |
# File 'lib/cmdx/rate_limit.rb', line 104 def condition_if @options[:if] end |
#condition_unless ⇒ Symbol, ...
109 110 111 |
# File 'lib/cmdx/rate_limit.rb', line 109 def condition_unless @options[:unless] end |
#cost ⇒ Numeric
91 92 93 94 95 96 |
# File 'lib/cmdx/rate_limit.rb', line 91 def cost raw = @options[:cost] return 1 if raw.nil? Float(raw) end |
#enabled? ⇒ Boolean
114 115 116 |
# File 'lib/cmdx/rate_limit.rb', line 114 def enabled? !key.nil? end |
#limiter ⇒ Symbol
86 87 88 |
# File 'lib/cmdx/rate_limit.rb', line 86 def limiter @options[:limiter] || :fixed_window end |
#max ⇒ Integer?
76 77 78 |
# File 'lib/cmdx/rate_limit.rb', line 76 def max @options[:max] end |
#namespace ⇒ String
71 72 73 |
# File 'lib/cmdx/rate_limit.rb', line 71 def namespace @options[:namespace] || "cmdx:rl" end |
#on_limit ⇒ Symbol
Returns :fail or :skip.
99 100 101 |
# File 'lib/cmdx/rate_limit.rb', line 99 def on_limit @options[:on_limit] || :fail end |
#per ⇒ Integer?
81 82 83 |
# File 'lib/cmdx/rate_limit.rb', line 81 def per @options[:per] end |
#process(task) { ... } ⇒ Object
When over limit, signals skip! or fail! on task — control does
not return to the caller of #process.
Runs the limiter once, then yields when admitted or inactive.
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/cmdx/rate_limit.rb', line 147 def process(task) return yield unless enabled? return yield unless Util.satisfied?(condition_if, condition_unless, task) store_key = StoreKey.task_key(task, namespace:, resolver: key, class_scoped: true) return yield if store_key.nil? quota = Quota.new( task:, store_key:, max: Integer(max), per: Integer(per), cost:, limiter:, options: @options ) admission = invoke_limiter(task, quota) if admission.admitted? admitted!(task, store_key, admission, quota) yield else exceeded!(task, store_key, admission, quota) end end |