Class: Rubino::Documents::Limits::Budget
- Inherits:
-
Object
- Object
- Rubino::Documents::Limits::Budget
- Defined in:
- lib/rubino/documents/limits.rb
Overview
Per-conversion resource counter. Not thread-safe by design: a single conversion runs on one thread; the cancel_token IS the cross-thread signal and is itself lock-free/monotonic.
Instance Attribute Summary collapse
-
#bytes ⇒ Object
readonly
Returns the value of attribute bytes.
-
#elements ⇒ Object
readonly
Returns the value of attribute elements.
-
#max_decompressed_bytes ⇒ Object
readonly
Returns the value of attribute max_decompressed_bytes.
Instance Method Summary collapse
-
#add_bytes(count) ⇒ Object
Account for ‘count` extracted bytes WITHOUT advancing the element count (e.g. a raw whole-file read in html/csv/json/xml/plain).
-
#initialize(max_elements:, max_decompressed_bytes:, wall_clock_seconds:, cancel_token: nil) ⇒ Budget
constructor
A new instance of Budget.
-
#tick(elements: 1, bytes: 0) ⇒ Object
Account for one (or more) processed units and ‘bytes` of extracted text, then enforce every cap.
Constructor Details
#initialize(max_elements:, max_decompressed_bytes:, wall_clock_seconds:, cancel_token: nil) ⇒ Budget
Returns a new instance of Budget.
160 161 162 163 164 165 166 167 168 169 |
# File 'lib/rubino/documents/limits.rb', line 160 def initialize(max_elements:, max_decompressed_bytes:, wall_clock_seconds:, cancel_token: nil) @max_elements = max_elements @max_decompressed_bytes = max_decompressed_bytes @wall_clock = wall_clock_seconds @deadline = monotonic + wall_clock_seconds @cancel_token = cancel_token @elements = 0 @bytes = 0 @since_clock = 0 end |
Instance Attribute Details
#bytes ⇒ Object (readonly)
Returns the value of attribute bytes.
158 159 160 |
# File 'lib/rubino/documents/limits.rb', line 158 def bytes @bytes end |
#elements ⇒ Object (readonly)
Returns the value of attribute elements.
158 159 160 |
# File 'lib/rubino/documents/limits.rb', line 158 def elements @elements end |
#max_decompressed_bytes ⇒ Object (readonly)
Returns the value of attribute max_decompressed_bytes.
158 159 160 |
# File 'lib/rubino/documents/limits.rb', line 158 def max_decompressed_bytes @max_decompressed_bytes end |
Instance Method Details
#add_bytes(count) ⇒ Object
Account for ‘count` extracted bytes WITHOUT advancing the element count (e.g. a raw whole-file read in html/csv/json/xml/plain). Still checks the byte ceiling, the clock, and cancellation.
198 199 200 |
# File 'lib/rubino/documents/limits.rb', line 198 def add_bytes(count) tick(elements: 0, bytes: count) end |
#tick(elements: 1, bytes: 0) ⇒ Object
Account for one (or more) processed units and ‘bytes` of extracted text, then enforce every cap. Call once per element in the converter’s hot loop. Raises Rubino::Interrupted on cancel, CapExceeded on any cap.
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/rubino/documents/limits.rb', line 174 def tick(elements: 1, bytes: 0) @elements += elements @bytes += bytes @since_clock += elements # Cancellation first: a cancelled turn must abort even mid-bomb. raise Rubino::Interrupted if @cancel_token&.cancelled? raise CapExceeded, "element count cap (#{@max_elements}) exceeded" if @elements > @max_elements if @bytes > @max_decompressed_bytes raise CapExceeded, "decompressed size cap (#{@max_decompressed_bytes} bytes) exceeded" end # Reading a clock per element is measurable in a tight 1M-iteration # loop; sample it every TICK_INTERVAL elements instead. return unless @since_clock >= TICK_INTERVAL @since_clock = 0 raise CapExceeded, "wall-clock budget (#{format("%.0f", @wall_clock)}s) exceeded" if monotonic > @deadline end |