Skip to content

fix(#2553) : AsyncSequence.asObservable() runs on background thread #2662

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

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

suojae
Copy link

@suojae suojae commented Apr 16, 2025

Fixes #2553

Problem Description

The current implementation of AsyncSequence.asObservable() can potentially execute on the main thread, which may cause UI blocking issues. This becomes especially problematic when the AsyncSequence performs time-consuming operations.

Changes

Modified AsyncSequence.asObservable() to use Task.detached, ensuring the sequence always runs on a background thread. This change guarantees that AsyncSequence operations won't block the main thread.

Testing

  • Successfully passed all existing tests
  • Added and passed test cases that verify execution on background threads
  • Included additional test cases covering edge scenarios (with sleep operations, error handling)

@@ -60,7 +60,7 @@ public extension AsyncSequence {
/// - returns: An `Observable` of the async sequence's type
func asObservable() -> Observable<Element> {

Choose a reason for hiding this comment

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

What do you think about adding a new param to decide whether to use Task or Task.detached?

Copy link
Author

Choose a reason for hiding this comment

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

I think adding a parameter is a good idea to provide flexibility. I'm considering implementing it like this:

func asObservable(detached: Bool = true) -> Observable<Element> {
    // Use Task.detached or Task based on the parameter
}

With true as the default value, it would still solve the original issue by running on a background thread, while giving users the option to use regular Task when they want to maintain the current context's priority.

What do you think about this approach and the default value being true?

Choose a reason for hiding this comment

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

It sounds good. I’ve also seen a similar implementation in another library, which takes the same approach

About the default value of detached, I think false should be used to avoid introducing a breaking change.

Copy link
Author

@suojae suojae Apr 17, 2025

Choose a reason for hiding this comment

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

I've implemented the parameter as suggested, with false as the default value to maintain backward compatibility.

func asObservable(detached: Bool = false) -> Observable<Element> {
    // Implementation uses Task.detached when detached=true, otherwise uses Task
}

All tests are passing. Thanks!

Choose a reason for hiding this comment

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

Nice 🙏

@suojae suojae force-pushed the fix/async-sequence-background-thread branch 2 times, most recently from 9966097 to ef95a2a Compare April 17, 2025 17:08
Co-authored-by: Petrus Nguyễn Thái Học <hoc081098@gmail.com>
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.

AsyncSequence.asObservable() effect is not as expected
2 participants