Skip to content

Is this logging appropriate? #382

Closed
Closed

Description

@jesseduffield

I'm seeing some warnings in my tests about tasks that 'may have ended with unhandled exception.'

I can't tell if this is async being overly cautious, or if I'm actually doing something wrong. As far as I can tell, this code is correct:

Code:

    def async_map(items:, concurrency_limit: Float::INFINITY, &block)
      result = []

      Async do
        semaphore = Async::Semaphore.new(concurrency_limit)

        tasks = items.map do |item|
          semaphore.async do
            yield(item)
          end
        end

        result = tasks.map(&:wait)
      end.wait

      return result
    end

Spec:

require "rails_helper"

RSpec.describe AsyncUtils do
  describe ".async_map" do
    subject { described_class.async_map(items:, concurrency_limit:, &block) }

    context "when the block raises an error" do
      let(:block) { ->(_) { raise "test error" } }
      let(:items) { [1, 2, 3] }
      let(:concurrency_limit) { Float::INFINITY }

      it "propagates the error" do
        expect { subject }.to raise_error("test error")
      end
    end
  end
end

Test output:

    when the block raises an error
  0.0s     warn: Async::Task [oid=0x7b34] [ec=0x7b48] [pid=150195] [2025-04-09 11:52:45 +0000]
               | Task may have ended with unhandled exception.
               |   RuntimeError: test error
               |   → spec/services/async_utils_spec.rb:40 in `block (5 levels) in <top (required)>'
               |     app/services/async_utils.rb:20 in `block (3 levels) in async_map'
               |     /api-bundle/ruby/3.3.0/gems/async-2.23.1/lib/async/semaphore.rb:68 in `block in async'
               |     /api-bundle/ruby/3.3.0/gems/async-2.23.1/lib/async/task.rb:200 in `block in run'
               |     /api-bundle/ruby/3.3.0/gems/async-2.23.1/lib/async/task.rb:438 in `block in schedule'
  0.0s     warn: Async::Task [oid=0x7b5c] [ec=0x7b70] [pid=150195] [2025-04-09 11:52:45 +0000]
               | Task may have ended with unhandled exception.
               |   RuntimeError: test error
               |   → spec/services/async_utils_spec.rb:40 in `block (5 levels) in <top (required)>'
               |     app/services/async_utils.rb:20 in `block (3 levels) in async_map'
               |     /api-bundle/ruby/3.3.0/gems/async-2.23.1/lib/async/semaphore.rb:68 in `block in async'
               |     /api-bundle/ruby/3.3.0/gems/async-2.23.1/lib/async/task.rb:200 in `block in run'
               |     /api-bundle/ruby/3.3.0/gems/async-2.23.1/lib/async/task.rb:438 in `block in schedule'
  0.0s     warn: Async::Task [oid=0x7b84] [ec=0x7b98] [pid=150195] [2025-04-09 11:52:45 +0000]
               | Task may have ended with unhandled exception.
               |   RuntimeError: test error
               |   → spec/services/async_utils_spec.rb:40 in `block (5 levels) in <top (required)>'
               |     app/services/async_utils.rb:20 in `block (3 levels) in async_map'
               |     /api-bundle/ruby/3.3.0/gems/async-2.23.1/lib/async/semaphore.rb:68 in `block in async'
               |     /api-bundle/ruby/3.3.0/gems/async-2.23.1/lib/async/task.rb:200 in `block in run'
               |     /api-bundle/ruby/3.3.0/gems/async-2.23.1/lib/async/task.rb:438 in `block in schedule'
  0.0s     warn: Async::Task [oid=0x7bac] [ec=0x7bc0] [pid=150195] [2025-04-09 11:52:45 +0000]
               | Task may have ended with unhandled exception.
               |   RuntimeError: test error
               |   → spec/services/async_utils_spec.rb:40 in `block (5 levels) in <top (required)>'
               |     app/services/async_utils.rb:20 in `block (3 levels) in async_map'
               |     /api-bundle/ruby/3.3.0/gems/async-2.23.1/lib/async/semaphore.rb:68 in `block in async'
               |     /api-bundle/ruby/3.3.0/gems/async-2.23.1/lib/async/task.rb:200 in `block in run'
               |     /api-bundle/ruby/3.3.0/gems/async-2.23.1/lib/async/task.rb:438 in `block in schedule'

So my question is: should I just disable these noisy logs, or do they necessarily point to actual problems in my code? Thanks.

Activity

  1. ioquatix commented on Apr 9, 2025

    @ioquatix
    Member

    You should check out this PR: socketry/async-await#10, basically add finished: false which indicates that while we aren't waiting yet, we will eventually wait.

    finished: nil (the default) means unspecified and will log an exception because we don't know if it is going to be handled or not. Unfortunately Async cannot read the future.

  2. locked and limited conversation to collaborators on Apr 9, 2025
  3. converted this issue into a discussion #383 on Apr 9, 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