Class: Zeridion::Flare::Worker::CancellationToken

Inherits:
Object
  • Object
show all
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

Constructor Details

#initializeCancellationToken

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.

Returns:

  • (Boolean)

    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.

Raises:



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.

Parameters:

  • seconds (Numeric)

Returns:

  • (Boolean)

    true if it woke due to cancellation, false on timeout.



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