Skip to content

Wrapping a fiber in an Async Task #429

Closed

Description

@cramt

Is it possible to easily take an existing fiber i got from a library and basically just turn it into a task so i can await it, or await it by it self?

Its obviously a "finite" fiber that fits into what an async task expects, aka it yields nil until it at some point yields something truthy and then closes

Activity

  1. ioquatix commented on Nov 11, 2025

    @ioquatix
    Member

    There are specific requirements around the life cycle of a fiber:

    async/lib/async/task.rb

    Lines 451 to 465 in a093f3a

    begin
    completed!(yield)
    rescue Stop
    stopped!
    rescue StandardError => error
    failed!(error)
    rescue Exception => exception
    failed!(exception)
    # This is a critical failure, we should stop the reactor:
    raise
    ensure
    # Console.info(self) {"Task ensure $! = #{$!} with #{@children&.size.inspect} children!"}
    finish!
    end

    Therefore, it's not possible to wrap an existing fiber as it won't emit those events.

    However, fibers are pretty cheap and will get scheduled even if not wrapped in tasks:

    Async do |parent|
      3.times do
        parent.async do
          Fiber.new do
            sleep 1
            puts "#{Fiber.current} done."
          end.resume
        end
      end
    end
    
    # All done at the same time:
    #<Fiber:0x00007fdd70f269d0 (irb):5 (resumed)> done.
    #<Fiber:0x00007fdd70f226a0 (irb):5 (resumed)> done.
    #<Fiber:0x00007fdd70f21ae8 (irb):5 (resumed)> done.
    # => #<Async::Task:0x0000000000002290>

    So I suggest something like this:

    Async do
      # Resume it once:
      existing_fiber.resume
      
      # Or if it can yield values:
      while value = existing_fiber.resume
        process(value)
      end
    
      # Or if you just want to resume it until completion:
      while existing_fiber.alive?
        existing_fiber.resume
      end
    end

    Hope that helps!

  2. cramt commented on Nov 13, 2025

    @cramt
    Author

    Thanks, but doesnt busy waiting like this block the async scheduler? if my fiber basically equivilant to

    start = Time.now.to_i
    Fiber.new do
    	loop do
    		if start + 5 > Time.now.to_i
    			Fiber.yield nil
    		elsif
    			return "some value"
    		end
    	end
    end

    should i throw a sleep in there somewhere? or some other way to tell the scheduler "hey this async task here, you can just schedule it at the end of whatever event queue you have"

  3. locked and limited conversation to collaborators on Nov 13, 2025
  4. converted this issue into a discussion #430 on Nov 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions