Class: Teek::BackgroundRactor4x::BackgroundWork
- Inherits:
-
Object
- Object
- Teek::BackgroundRactor4x::BackgroundWork
- Defined in:
- lib/teek/background_ractor4x.rb
Overview
Ractor-based background work using Ruby 4.x Ractor::Port for streaming and Ractor.shareable_proc for blocks.
Defined Under Namespace
Classes: TaskContext
Instance Method Summary collapse
-
#close ⇒ self
Force-close the Ractor and all associated resources.
-
#done? ⇒ Boolean
Whether the worker has finished.
-
#initialize(app, data, worker: nil) {|task, data| ... } ⇒ BackgroundWork
constructor
A new instance of BackgroundWork.
-
#on_done { ... } ⇒ self
Register a callback for when the worker finishes.
-
#on_message {|msg| ... } ⇒ self
Register a callback for custom messages sent by the worker via TaskContext#send_message.
-
#on_progress {|value| ... } ⇒ self
Register a callback for progress updates from the worker.
-
#pause ⇒ self
Pause the worker.
-
#paused? ⇒ Boolean
Whether the worker is paused.
-
#resume ⇒ self
Resume a paused worker.
-
#send_message(msg) ⇒ self
Send a message to the worker.
-
#start ⇒ self
Explicitly start the background work.
-
#stop ⇒ self
Request the worker to stop.
Constructor Details
#initialize(app, data, worker: nil) {|task, data| ... } ⇒ BackgroundWork
Returns a new instance of BackgroundWork.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/teek/background_ractor4x.rb', line 63 def initialize(app, data, worker: nil, &block) @app = app @data = data @work_block = block || (worker && proc { |t, d| worker.new.call(t, d) }) @callbacks = { progress: nil, done: nil, message: nil } @started = false @done = false @paused = false # Communication @output_queue = Thread::Queue.new @control_port = nil # Set by worker, received back @pending_messages = [] # Queued until control_port ready @worker_ractor = nil @bridge_thread = nil end |
Instance Method Details
#close ⇒ self
Force-close the Ractor and all associated resources.
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/teek/background_ractor4x.rb', line 154 def close @done = true # Send stop to let the worker terminate itself — Ruby 4.x doesn't # allow closing a Ractor from outside. The message thread will # raise StopIteration on the Ractor's main thread, which triggers # the rescue block that sends [:done] to the output port and exits # the Ractor cleanly. begin @control_port&.send(:stop) rescue Ractor::ClosedError # Already closed end @control_port = nil # Wait for the bridge thread to receive [:done] and exit. Without # this, the zombie bridge thread blocks subsequent operations on # Windows (Ractor::Port#receive holds the GVL). @bridge_thread&.join(2) self end |
#done? ⇒ Boolean
Returns whether the worker has finished.
202 203 204 |
# File 'lib/teek/background_ractor4x.rb', line 202 def done? @done end |
#on_done { ... } ⇒ self
Register a callback for when the worker finishes. Auto-starts the task if not already started.
94 95 96 97 98 |
# File 'lib/teek/background_ractor4x.rb', line 94 def on_done(&block) @callbacks[:done] = block maybe_start self end |
#on_message {|msg| ... } ⇒ self
Register a callback for custom messages sent by the worker via Teek::BackgroundRactor4x::BackgroundWork::TaskContext#send_message.
104 105 106 107 |
# File 'lib/teek/background_ractor4x.rb', line 104 def (&block) @callbacks[:message] = block self end |
#on_progress {|value| ... } ⇒ self
Register a callback for progress updates from the worker. Auto-starts the task if not already started.
84 85 86 87 88 |
# File 'lib/teek/background_ractor4x.rb', line 84 def on_progress(&block) @callbacks[:progress] = block maybe_start self end |
#pause ⇒ self
Pause the worker. The worker will block on the next Teek::BackgroundRactor4x::BackgroundWork::TaskContext#yield or Teek::BackgroundRactor4x::BackgroundWork::TaskContext#check_pause until #resume is called.
130 131 132 133 134 |
# File 'lib/teek/background_ractor4x.rb', line 130 def pause @paused = true (:pause) self end |
#paused? ⇒ Boolean
Returns whether the worker is paused.
207 208 209 |
# File 'lib/teek/background_ractor4x.rb', line 207 def paused? @paused end |
#resume ⇒ self
Resume a paused worker.
138 139 140 141 142 |
# File 'lib/teek/background_ractor4x.rb', line 138 def resume @paused = false (:resume) self end |
#send_message(msg) ⇒ self
Send a message to the worker. The worker can receive it via Teek::BackgroundRactor4x::BackgroundWork::TaskContext#check_message or Teek::BackgroundRactor4x::BackgroundWork::TaskContext#wait_message. Messages are queued if the worker's control port isn't ready yet.
114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/teek/background_ractor4x.rb', line 114 def (msg) if @control_port begin @control_port.send(msg) rescue Ractor::ClosedError # Port already closed, task is done - ignore end else @pending_messages << msg end self end |
#start ⇒ self
Explicitly start the background work. Called automatically by #on_progress and #on_done; only needed when using #on_message alone.
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/teek/background_ractor4x.rb', line 178 def start return self if @started @started = true # Wrap in isolated proc for Ractor sharing. The block can only access # its parameters (task, data), not outer-scope variables. isolation_error = false begin shareable_block = Ractor.shareable_proc(&@work_block) rescue Ractor::IsolationError isolation_error = true end if isolation_error raise Ractor::IsolationError, "Background work block must not reference outside variables (including `app`). " \ "Use t.yield() to send results to on_progress, which runs on the main thread." end start_ractor(shareable_block) start_polling self end |
#stop ⇒ self
Request the worker to stop. Raises StopIteration inside the worker
on the next Teek::BackgroundRactor4x::BackgroundWork::TaskContext#check_message or Teek::BackgroundRactor4x::BackgroundWork::TaskContext#yield.
147 148 149 150 |
# File 'lib/teek/background_ractor4x.rb', line 147 def stop (:stop) self end |