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

events: simplify on implementation #41851

Closed
wants to merge 9 commits into from
Closed

Conversation

ronag
Copy link
Member

@ronag ronag commented Feb 4, 2022

Implement AsyncIterables using AsyncGenerator.

@ronag ronag requested a review from benjamingr February 4, 2022 12:59
@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/streams

@nodejs-github-bot nodejs-github-bot added events Issues and PRs related to the events subsystem / EventEmitter. needs-ci PRs that need a full CI run. labels Feb 4, 2022
@@ -113,39 +113,6 @@ async function throwInLoop() {
assert.strictEqual(ee.listenerCount('error'), 0);
}

async function next() {
Copy link
Member

Choose a reason for hiding this comment

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

why these tests deleted?

Copy link
Member Author

@ronag ronag Feb 4, 2022

Choose a reason for hiding this comment

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

They don't work with an async generator implementation. Please do have a look at it. But I can't find a way to make that test pass with an async generator and assuming async generators are "correct" then the test is "incorrect".

Copy link
Member

Choose a reason for hiding this comment

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

They don't work with an async generator implementation

What is the output with the async iterator implementation?

These tests specifically check that if the user asked for two events and then closed the iterator they still get those two events and not one event and then the iterator closing. That behavior is quite explicit - though we can talk about changing it (it'd be a breaking change though I doubt a lot of users are relying on this behavior)

Copy link
Member Author

@ronag ronag Feb 4, 2022

Choose a reason for hiding this comment

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

So the problem here is the return() which doesn't actually guarantee that the last iterable.next() (where you expect { done: true }) will ever resolve since the async generator will never reach the yield statement while waiting for the promise to resolve. As far as I know there is not way to do this in an async generator. It's not a problem for for await loops so I'm not quite sure what exactly the spec or users would expect out of this use case?

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member Author

@ronag ronag Feb 4, 2022

Choose a reason for hiding this comment

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

Can't see? Bad link?

Copy link
Member Author

@ronag ronag Feb 4, 2022

Choose a reason for hiding this comment

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

I don't know about the specifics of this but it seems weird to me that we want to achieve a behaviour which is not achievable with an async generator. Feels a bit like outside of spec. Maybe I'm a bit too hung up on assuming async generator is the "correct" way.

Copy link
Member

Choose a reason for hiding this comment

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

I don't know about the specifics of this but it seems weird to me that we want to achieve a behaviour which is not achievable with an async generator.

Not dropping these events is why the implementation didn't use an async generator initially - it's OK to change that if you think the simplification is worth losing that API guarantee.

It's true users who for... await will next() one at a time but implementations (think from) can ask for multiple values at once and this changes the behavior of the last chunks in the stream.

Copy link
Member Author

Choose a reason for hiding this comment

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

if you think the simplification is worth losing that API guarantee.

I think so. But I'm not sure if my opinion is sufficient here. I don't understand why we wanted this API guarantee to begin with.

@vweevers
Copy link
Contributor

vweevers commented Feb 4, 2022

*simplify?

lib/events.js Outdated Show resolved Hide resolved
lib/events.js Outdated Show resolved Hide resolved
@vweevers
Copy link
Contributor

vweevers commented Feb 4, 2022

*simplify?

@ronag To clarify, I meant whether "simply" in the PR title and commit is a typo? If not, I don't understand the description

@ronag ronag changed the title events: simply on implementation events: simplify on implementation Feb 4, 2022
@ronag ronag requested a review from mcollina February 4, 2022 13:35
});
}
} finally {
eventTargetAgnosticRemoveListener(emitter, event, eventHandler);
Copy link
Member

Choose a reason for hiding this comment

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

So the behavior here is to drop all events when the iterator is returned right?

So if I .next() 5 times and then .return I would get { done: true, value: undefined } on all 5?

Copy link
Member Author

Choose a reason for hiding this comment

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

yes, I believe so

@benjamingr
Copy link
Member

@ronag
Copy link
Member Author

ronag commented Feb 4, 2022

This isn't really for perf inc but here are the results relative to node 17.3.1

readline/readline-iterable.js n=10             ***    -11.37 %       ±5.09% ±6.84% ±9.02%
readline/readline-iterable.js n=100            ***      6.81 %       ±3.23% ±4.32% ±5.67%
readline/readline-iterable.js n=1000                    0.44 %       ±2.49% ±3.31% ±4.31%
readline/readline-iterable.js n=10000          ***      4.60 %       ±0.81% ±1.08% ±1.40%
readline/readline-iterable.js n=100000         ***      3.28 %       ±0.57% ±0.76% ±0.99%
readline/readline-iterable.js n=1000000        ***      1.06 %       ±0.53% ±0.71% ±0.92%

asd2 Outdated Show resolved Hide resolved
@ronag ronag added request-ci Add this label to start a Jenkins CI on a PR. and removed needs-ci PRs that need a full CI run. labels Feb 6, 2022
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Feb 6, 2022
@nodejs-github-bot
Copy link
Collaborator

@ronag ronag added the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Feb 6, 2022
@nodejs-github-bot
Copy link
Collaborator

@aduh95
Copy link
Contributor

aduh95 commented Feb 11, 2022

This needs reviews.

@aduh95 aduh95 added review wanted PRs that need reviews. and removed author ready PRs that have at least one approval, no pending requests for changes, and a CI started. labels Feb 11, 2022
@benjamingr
Copy link
Member

@aduh95 the reason these are stalled is that there is a tradeoff here - this impl is simpler but slower and breaks several guarantees users might but probably don't rely on. The alternative is #41276

@ronag
Copy link
Member Author

ronag commented Feb 11, 2022

Yea, I openend this as I have concerns about the complexity of #41276. Was hoping to convince that given how simple it can be this is preferable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
events Issues and PRs related to the events subsystem / EventEmitter. review wanted PRs that need reviews.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants