Class: Zeridion::Flare::Worker::CancellationToken
- Inherits:
-
Object
- Object
- Zeridion::Flare::Worker::CancellationToken
- Defined in:
- lib/zeridion_flare/worker/cancellation_token.rb
Overview
Cooperative cancellation handle handed to every job via JobContext.
Cancellation in Ruby is COOPERATIVE ONLY (decision D6): the worker never uses Thread#raise, Thread#kill, or Timeout.timeout — those are unsafe around Net::HTTP / pg / redis and can corrupt connection state. A CPU-bound or blocking handler that never checks the token is uninterruptible from the SDK and is bounded only by the server reaper.
Handlers cooperate by polling #cancelled? / calling #check! at safe points, and by using #wait(seconds) instead of Kernel#sleep so a pending sleep wakes immediately on cancel. Cancellation fires on: a server "cancel" heartbeat response, host shutdown (SIGTERM/SIGINT), or the local per-job timeout. In every case the job ultimately acks "failed" (D1), never "cancelled".
Instance Method Summary collapse
-
#cancel! ⇒ Object
Request cancellation and wake any thread blocked in #wait.
-
#cancelled? ⇒ Boolean
True once cancellation has been requested.
-
#check! ⇒ Object
Raise JobCancelledError if cancellation has been requested.
-
#initialize ⇒ CancellationToken
constructor
A new instance of CancellationToken.
-
#wait(seconds) ⇒ Boolean
Interruptible, monotonic sleep.
Constructor Details
#initialize ⇒ CancellationToken
Returns a new instance of CancellationToken.
21 22 23 24 25 |
# File 'lib/zeridion_flare/worker/cancellation_token.rb', line 21 def initialize @mutex = Mutex.new @cond = ConditionVariable.new @cancelled = false end |
Instance Method Details
#cancel! ⇒ Object
Request cancellation and wake any thread blocked in #wait. Idempotent. Internal — called by the runtime, not by handlers.
74 75 76 77 78 79 |
# File 'lib/zeridion_flare/worker/cancellation_token.rb', line 74 def cancel! @mutex.synchronize do @cancelled = true @cond.broadcast end end |
#cancelled? ⇒ Boolean
Returns true once cancellation has been requested.
28 29 30 |
# File 'lib/zeridion_flare/worker/cancellation_token.rb', line 28 def cancelled? @mutex.synchronize { @cancelled } end |
#check! ⇒ Object
Raise JobCancelledError if cancellation has been requested. Call at natural checkpoints in a long handler.
34 35 36 |
# File 'lib/zeridion_flare/worker/cancellation_token.rb', line 34 def check! raise JobCancelledError if cancelled? end |
#wait(seconds) ⇒ Boolean
Interruptible, monotonic sleep. Returns early (true) the moment
cancellation is requested; otherwise sleeps up to seconds and
returns false. Uses ConditionVariable#wait, which is monotonic-clock
based, so it is immune to wall-clock jumps. seconds <= 0 returns
immediately.
An infinite seconds (Float::INFINITY) means "block until cancelled":
ConditionVariable#wait rejects a non-finite timeout ("Inf out of Time
range"), so we pass nil (wait forever) instead of an out-of-range
deadline. #run relies on this to park the main thread until a signal.
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/zeridion_flare/worker/cancellation_token.rb', line 51 def wait(seconds) infinite = seconds.respond_to?(:infinite?) && seconds.infinite? deadline = infinite ? nil : monotonic_now + seconds.to_f @mutex.synchronize do loop do return true if @cancelled if deadline.nil? # Block until #cancel! broadcasts (no timeout). @cond.wait(@mutex) next end remaining = deadline - monotonic_now return false if remaining <= 0 @cond.wait(@mutex, remaining) end end end |