Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

If a task returns an exception value, do not raise it in #wait. #270

Merged
merged 1 commit into from
Aug 14, 2023

Conversation

Math2
Copy link
Contributor

@Math2 Math2 commented Aug 14, 2023

Types of Changes

  • Bug fix.

Contribution

Notes

If a task returns an exception value (without raising it), #wait raises it.

require 'async'
Sync do
	t = Async do
		StandardError.new
	end
	t.wait # raises StandardError!
end

Seems like something that would rarely happen, but it happened to me with an assert_raises at the end of a task (apparently, it returns the exception that was raised).

@ioquatix
Copy link
Member

This looks okay to me, although it breaks the behaviour/compatibilty.

Can you follow the existing explicit code style if ... with explicit return.

We need to be convinced that:

  1. Every code path that causes to enter failed state also causes @result to be an exception (otherwise I suppose raise will fail).
  2. Can there be cases where someone is assigning an error without entering failed state, expecting it to raise on #wait?

@Math2
Copy link
Contributor Author

Math2 commented Aug 14, 2023

This looks okay to me, although it breaks the behaviour/compatibilty.

Can you follow the existing explicit code style if ... with explicit return.

Alright.

We need to be convinced that:

1. Every code path that causes to enter failed state also causes `@result` to be an exception (otherwise I suppose `raise` will fail).

Thankfully the code makes it pretty clear. @status is always set when @result is. @status is only set to :failed in one place.

2. Can there be cases where someone is assigning an error without entering failed state, expecting it to raise on `#wait`?

Hopefully there aren't any callers that expect that just returning an exception (or setting it manually with #result=) would automatically raise it, but, there's a risk I guess...

To be really safe there could be a deprecation warning instead.

There are callers that expect the exception to be available via #result after a task failed in the test suite though (and those still work fine).

@ioquatix
Copy link
Member

ioquatix commented Aug 14, 2023

I think the expectation that

Async{StandardError.new}.wait

should raise an exception is undefined at best. The fact that existing tests don't break is a testament to that.

However, with this PR, can we please add tests to cover the different use cases. In other words, let's not leave it up to chance going forward. Maybe documentation is a good idea too. Thanks!

Copy link
Member

@ioquatix ioquatix left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. We might consider backporting this... but honestly, I'm not sure if it matters.

@ioquatix ioquatix merged commit 72ca9ca into socketry:main Aug 14, 2023
@Math2
Copy link
Contributor Author

Math2 commented Aug 14, 2023

We might consider backporting this... but honestly, I'm not sure if it matters.

Nah, I don't think so either.

@ioquatix
Copy link
Member

This also made me think about calling #wait on stopped tasks. Should it raise Async::Stop?

@Math2
Copy link
Contributor Author

Math2 commented Aug 14, 2023

That could propagate and stop the calling task (if not caught) right? Should be some other exception instead.

But, calling #wait on a stopped task (expecting to get nil) is the kind of thing I would expect callers would do in practice. It could be pretty convenient.

@ioquatix
Copy link
Member

I'll have to think about it. Such a change is tricky.

mattbrictson added a commit to mattbrictson/webmock that referenced this pull request Oct 24, 2023
The `async` gem recently made a breaking API change that was released in
patch version 2.6.4.[^1] Following the change, async tasks that return
an  exception object will no longer raise that exception when `wait` is
called.

The `Async::HTTP` specs in webmock were written to leverage the old
behavior of `wait`. Since async 2.6.4 was released, these specs have
been failing in CI.

This commit fixes the failing specs by updating how `wait` is used, such
that exceptions are still raised as expected in async 2.6.4. This should
restore CI to a working state.

[^1]: socketry/async#270
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants