lib/async/task.rb in async-2.14.0 vs lib/async/task.rb in async-2.14.1
- old
+ new
@@ -11,10 +11,12 @@
require 'console/event/failure'
require_relative 'node'
require_relative 'condition'
+Fiber.attr_accessor :async_task
+
module Async
# Raised when a task is explicitly stopped.
class Stop < Exception
# Used to defer stopping the current task until later.
class Later
@@ -184,10 +186,19 @@
if @status == :initialized
@status = :running
schedule do
@block.call(self, *arguments)
+ rescue => error
+ # I'm not completely happy with this overhead, but the alternative is to not log anything which makes debugging extremely difficult. Maybe we can introduce a debug wrapper which adds extra logging.
+ if @finished.nil?
+ Console::Event::Failure.for(error).emit("Task may have ended with unhandled exception.", severity: :warn)
+ # else
+ # Console::Event::Failure.for(error).emit(self, severity: :debug)
+ end
+
+ raise
end
else
raise RuntimeError, "Task already running!"
end
end
@@ -314,17 +325,17 @@
# Lookup the {Task} for the current fiber. Raise `RuntimeError` if none is available.
# @returns [Task]
# @raises[RuntimeError] If task was not {set!} for the current fiber.
def self.current
- Thread.current[:async_task] or raise RuntimeError, "No async task available!"
+ Fiber.current.async_task or raise RuntimeError, "No async task available!"
end
# Check if there is a task defined for the current fiber.
# @returns [Interface(:async) | Nil]
def self.current?
- Thread.current[:async_task]
+ Fiber.current.async_task
end
# @returns [Boolean] Whether this task is the currently executing task.
def current?
Fiber.current.equal?(@fiber)
@@ -356,16 +367,10 @@
# State transition into the failed state.
def failed!(exception = false)
@result = exception
@status = :failed
-
- if $DEBUG
- Fiber.blocking do
- $stderr.puts "Task #{self} failed:", exception.full_message
- end
- end
end
def stopped!
# Console.info(self, status:) {"Task #{self} was stopped with #{@children&.size.inspect} children!"}
@status = :stopped
@@ -392,15 +397,12 @@
finish!
end
def schedule(&block)
@fiber = Fiber.new(annotation: self.annotation) do
- set!
-
begin
completed!(yield)
- # Console.debug(self) {"Task was completed with #{@children.size} children!"}
rescue Stop
stopped!
rescue StandardError => error
failed!(error)
rescue Exception => exception
@@ -412,15 +414,11 @@
# Console.info(self) {"Task ensure $! = #{$!} with #{@children&.size.inspect} children!"}
finish!
end
end
+ @fiber.async_task = self
+
self.root.resume(@fiber)
- end
-
- # Set the current fiber's `:async_task` to this task.
- def set!
- # This is actually fiber-local:
- Thread.current[:async_task] = self
end
end
end