diff --git a/async.gemspec b/async.gemspec index a242b209..f3ee11b9 100644 --- a/async.gemspec +++ b/async.gemspec @@ -22,6 +22,7 @@ Gem::Specification.new do |spec| spec.add_dependency "console", "~> 1.10" spec.add_dependency "io-event", "~> 1.1" spec.add_dependency "timers", "~> 4.1" + spec.add_dependency "fiber-annotate" spec.add_development_dependency "bake-test" spec.add_development_dependency "bake-test-external" diff --git a/lib/async/node.rb b/lib/async/node.rb index cb8905b8..3475e80d 100644 --- a/lib/async/node.rb +++ b/lib/async/node.rb @@ -5,6 +5,8 @@ # Copyright, 2017, by Kent Gruber. # Copyright, 2022, by Shannon Skipper. +require 'fiber/annotate' + require_relative 'list' module Async @@ -109,20 +111,27 @@ def transient? def annotate(annotation) if block_given? - previous_annotation = @annotation - @annotation = annotation - yield - @annotation = previous_annotation + begin + current_annotation = @annotation + @annotation = annotation + return yield + ensure + @annotation = current_annotation + end else @annotation = annotation end end + def annotation + @annotation + end + def description @object_name ||= "#{self.class}:#{format '%#018x', object_id}#{@transient ? ' transient' : nil}" - if @annotation - "#{@object_name} #{@annotation}" + if annotation = self.annotation + "#{@object_name} #{annotation}" elsif line = self.backtrace(0, 1)&.first "#{@object_name} #{line}" else diff --git a/lib/async/task.rb b/lib/async/task.rb index 68c9aff8..a7dbf9cd 100644 --- a/lib/async/task.rb +++ b/lib/async/task.rb @@ -96,6 +96,22 @@ def backtrace(*arguments) @fiber&.backtrace(*arguments) end + def annotate(annotation, &block) + if @fiber + @fiber.annotate(annotation, &block) + else + super + end + end + + def annotation + if @fiber + @fiber.annotation + else + super + end + end + def to_s "\#<#{self.description} (#{@status})>" end @@ -309,7 +325,7 @@ def stop! end def schedule(&block) - @fiber = Fiber.new do + @fiber = Fiber.new(annotation: self.annotation) do set! begin diff --git a/test/async/task.rb b/test/async/task.rb index b0656b15..730845f8 100644 --- a/test/async/task.rb +++ b/test/async/task.rb @@ -17,6 +17,32 @@ def after super end + with '#annotate' do + it "can annotate the current task that has not started yet" do + task = Async::Task.new(reactor) do |task| + sleep + end + + task.annotate("Hello World") + + expect(task.annotation).to be == "Hello World" + end + + it "can annotate the current task that has started" do + task = Async::Task.new(reactor) do |task| + task.annotate("Hello World") + + sleep + end + + expect(task.fiber).to be_nil + + task.run + + expect(task.fiber.annotation).to be == "Hello World" + end + end + with '.yield' do it "can yield back to scheduler" do state = nil