Class: Philiprehberger::TimeoutKit::Deadline
- Inherits:
-
Object
- Object
- Philiprehberger::TimeoutKit::Deadline
- Defined in:
- lib/philiprehberger/timeout_kit/deadline.rb
Overview
A cooperative deadline that tracks remaining time and supports nesting.
Deadlines do not use Thread.raise. Instead, callers must explicitly call #check! at safe cancellation points.
Instance Attribute Summary collapse
-
#duration ⇒ Float
readonly
The original budget passed to new as
seconds. -
#expires_at ⇒ Float
readonly
The absolute monotonic time when the deadline expires.
-
#name ⇒ String?
readonly
The human-readable name for this deadline.
Instance Method Summary collapse
-
#check! ⇒ void
Check whether the deadline has expired.
-
#elapsed ⇒ Float
Return the number of seconds elapsed since the deadline was created.
-
#expired? ⇒ Boolean
Whether the primary deadline has expired.
-
#grace_remaining ⇒ Float
Return the remaining time in the grace period.
-
#in_grace? ⇒ Boolean
Whether the deadline is currently in the grace period.
-
#initialize(seconds, name: nil, grace: nil, on_expire: nil) ⇒ Deadline
constructor
Create a new deadline.
-
#on_expire { ... } ⇒ void
Register a callback that fires once when expiry is detected.
-
#progress ⇒ Float
Fraction of the original budget that has elapsed (0.0..1.0+).
-
#remaining ⇒ Float
Return the remaining time in seconds until the primary deadline.
Constructor Details
#initialize(seconds, name: nil, grace: nil, on_expire: nil) ⇒ Deadline
Create a new deadline.
27 28 29 30 31 32 33 34 35 36 |
# File 'lib/philiprehberger/timeout_kit/deadline.rb', line 27 def initialize(seconds, name: nil, grace: nil, on_expire: nil) @started_at = now @duration = seconds.to_f @expires_at = @started_at + seconds @name = name @grace_seconds = grace @grace_expires_at = @grace_seconds ? @expires_at + @grace_seconds : nil @on_expire = on_expire @expire_callback_fired = false end |
Instance Attribute Details
#duration ⇒ Float (readonly)
The original budget passed to new as seconds.
19 20 21 |
# File 'lib/philiprehberger/timeout_kit/deadline.rb', line 19 def duration @duration end |
#expires_at ⇒ Float (readonly)
Returns the absolute monotonic time when the deadline expires.
11 12 13 |
# File 'lib/philiprehberger/timeout_kit/deadline.rb', line 11 def expires_at @expires_at end |
#name ⇒ String? (readonly)
Returns the human-readable name for this deadline.
14 15 16 |
# File 'lib/philiprehberger/timeout_kit/deadline.rb', line 14 def name @name end |
Instance Method Details
#check! ⇒ void
This method returns an undefined value.
Check whether the deadline has expired.
50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/philiprehberger/timeout_kit/deadline.rb', line 50 def check! return unless expired? fire_expire_callback # If we have a grace period and are still within it, don't raise return if in_grace? = @name ? "Deadline '#{@name}' exceeded" : 'Deadline exceeded' raise DeadlineExceeded, end |
#elapsed ⇒ Float
Return the number of seconds elapsed since the deadline was created. This is a pure wall-clock reading from the monotonic clock and continues to increase past the original budget after expiration. Independent of #expired? and #in_grace?.
81 82 83 |
# File 'lib/philiprehberger/timeout_kit/deadline.rb', line 81 def elapsed now - @started_at end |
#expired? ⇒ Boolean
Whether the primary deadline has expired.
109 110 111 |
# File 'lib/philiprehberger/timeout_kit/deadline.rb', line 109 def expired? now >= @expires_at end |
#grace_remaining ⇒ Float
Return the remaining time in the grace period.
99 100 101 102 103 104 |
# File 'lib/philiprehberger/timeout_kit/deadline.rb', line 99 def grace_remaining return 0.0 unless @grace_expires_at r = @grace_expires_at - now r.negative? ? 0.0 : r end |
#in_grace? ⇒ Boolean
Whether the deadline is currently in the grace period. True only when the primary deadline has expired but the grace period has not.
117 118 119 120 121 |
# File 'lib/philiprehberger/timeout_kit/deadline.rb', line 117 def in_grace? return false unless @grace_expires_at expired? && now < @grace_expires_at end |
#on_expire { ... } ⇒ void
This method returns an undefined value.
Register a callback that fires once when expiry is detected.
42 43 44 |
# File 'lib/philiprehberger/timeout_kit/deadline.rb', line 42 def on_expire(&block) @on_expire = block end |
#progress ⇒ Float
Fraction of the original budget that has elapsed (0.0..1.0+). Exceeds 1.0 once the primary deadline has expired (and during grace period). Returns 1.0 if the original budget is zero.
90 91 92 93 94 |
# File 'lib/philiprehberger/timeout_kit/deadline.rb', line 90 def progress return 1.0 if @duration.zero? elapsed / @duration end |
#remaining ⇒ Float
Return the remaining time in seconds until the primary deadline. Can be negative during the grace period.
66 67 68 69 70 71 72 73 |
# File 'lib/philiprehberger/timeout_kit/deadline.rb', line 66 def remaining r = @expires_at - now if @grace_seconds r else r.negative? ? 0.0 : r end end |