Class: Phronomy::Task::MappedBackend Private

Inherits:
Backend
  • Object
show all
Defined in:
lib/phronomy/engine/task/mapped_backend.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Backend for Tasks created by #map.

A mapped task's lifecycle is driven entirely by the on_complete callback of its source task — it never spawns a thread of its own. MappedBackend transitions the owning task to :running immediately on initialization so that FSMSession treats it as an in-progress async action. Completion (or failure) is triggered externally via #transition! from the on_complete callback registered by #map.

await and join block until #unblock is called, which #map arranges by registering a second on_complete callback on the mapped task itself after the transform callback has been registered.

Instance Method Summary collapse

Methods inherited from Backend

#completed_error, #completed_value

Constructor Details

#initialize(task:) ⇒ MappedBackend

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of MappedBackend.



23
24
25
26
27
# File 'lib/phronomy/engine/task/mapped_backend.rb', line 23

def initialize(task:, &)
  super
  @done_queue = Queue.new
  task.transition!(:running)
end

Instance Method Details

#alive?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns false — a mapped task has no independent thread to kill.

Returns:

  • (Boolean)


62
63
64
# File 'lib/phronomy/engine/task/mapped_backend.rb', line 62

def alive?
  false
end

#cancel!self

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

No-op — mapped tasks carry no independent thread to cancel.

Returns:

  • (self)


69
70
71
# File 'lib/phronomy/engine/task/mapped_backend.rb', line 69

def cancel!
  self
end

#join(limit = nil) ⇒ Object?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Blocks until the mapped task completes, with an optional timeout.

Parameters:

  • limit (Numeric, nil) (defaults to: nil)

Returns:

  • (Object, nil)

    nil on timeout



77
78
79
80
81
82
83
84
85
86
87
# File 'lib/phronomy/engine/task/mapped_backend.rb', line 77

def join(limit = nil)
  if limit.nil?
    wait_result
  else
    begin
      Timeout.timeout(limit) { wait_result }
    rescue Timeout::Error
      nil
    end
  end
end

#unblock(value, error) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Unblocks await / join. Called by Phronomy::Task#map after the mapped task reaches a terminal state.



32
33
34
# File 'lib/phronomy/engine/task/mapped_backend.rb', line 32

def unblock(value, error)
  @done_queue.push([value, error])
end

#wait_resultObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Blocks until the mapped task reaches a terminal state.

Returns:

  • (Object)

    the mapped value

Raises:

  • (Exception)

    if the source task or the map block raised an error



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/phronomy/engine/task/mapped_backend.rb', line 40

def wait_result
  scheduler = Thread.current.thread_variable_get(Task::SCHEDULER_KEY)
  in_managed_fiber = !Fiber.respond_to?(:main) || Fiber.current != Fiber.main
  if scheduler && in_managed_fiber && !@task.done?
    scheduler.track_blocking_await
    waiting_fiber = Fiber.current
    @task.on_complete do |_value, _error|
      scheduler.complete_blocking_await
      scheduler.enqueue_fiber(-> { waiting_fiber.resume })
    end
    Fiber.yield(:cooperative_suspend)
  end

  value, error = @done_queue.pop
  raise error if error

  value
end