-
Notifications
You must be signed in to change notification settings - Fork 30k
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
Revert "module: have a single hooks thread for all workers" #53183
Conversation
Review requested:
|
I've added myself to @nodejs/loaders to be notified and catch those earlier. I'm sorry for the delayed review. |
We could also land this revert in v22 until a follow-up PR is made to restore previous capabilities. |
@dygabo you did great work for this change, but I don't think we can ship "one loader" without the support of calling register inside worker threads. That's needed for quite a lot of uses cases from running unit tests in workers, to hot reload, to just simply reusing code across the ecosystem. |
@mcollina I see. just fwiw these decisions were discussed on the original PR and on slack. After review the conclusion was to explicitly have it like this until |
@dygabo |
@ShogunPanda I have seen that but as discussed on the other PR I did not see a quick solution to that yet. That is the cause of the hanging indeed and removing it makes it not hang but that is not a solution to commit now IMO. Current implementation starts from the premise that there is an internal worker for the customization hooks that gets created by the main thread (that is because the main thread has a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change that this PR intends to revert was a bugfix, so reverting it just reintroduces the bug; so therefore we would need to land it a second time to fix the bug again. We’ve heard frequent feedback from users that changes to the hooks APIs are annoying, so we should try to avoid unnecessary churn. Before we revert this, we should investigate other solutions.
It seems clear that calling register
from a worker thread and have it do nothing, or crash, is a bug. However there’s a band-aid for that: Node could error when register
is called from a worker thread. That should be a simple fix that we could ship quickly without needing a revert/re-land cycle, and users can react to it by wrapping their register
calls in if (isMainThread)
, which would not need to be reverted later. Then if we find a way to make register
behave from worker threads the same way it acts on the main thread, we can enable it on worker threads and remove the error.
It’s never been part of the design to allow for different hooks to apply to different threads. From the start of the off-thread discussion, performance has always been a core concern; that’s why it was the intent that there never be more than one hooks thread per process, regardless of how many user threads there are. It’s interesting that folks have found uses for a “one hooks thread per worker thread” model, but that behavior was an accident. We could potentially support it in addition to the intended design, but I think it would be better to back up and ask what the use cases are that are satisfied by such a model and evaluate the best method for achieving them.
Me neither, I have tried all day long.
I think this is the best way to solve the current starving.
I agree. They should not be affected.
I instead think (and incurred) into the new limitation as not viable. |
This is not a viable solution. When Node is run in the default case where no hooks are registered, it needs to be running just a single thread. We can’t create the hooks thread all the time whether or not the user might use it; that would be a large performance penalty for anyone not using the hooks API. |
I see. It totally makes sense. In my opinion I would keep the separate threads (as it is for instance in 22.1) and only start them when needed by a worker thread. This way we don't have to keep a single thread that might run different chains.
Note that the need for different chains per worker is totally foreseeable, for instance:
These are only examples, obviously. |
That’s not a use case intended by the current design. That’s not to say it’s undesirable, but it’s a feature request for something in addition to the more common use case of “I want to write my entire app in TypeScript, and some of my app code runs in worker threads, and I want to register hooks to transpile the whole app.” I think you should open a separate issue with the specific use case(s) you have in mind, with less focus on the implementation details of things like “the user wants to spawn two workers.” Like for example the first one, if phrased as “The user wants to transpile TypeScript and CoffeeScript” is completely possible today, by filtering on file extension: a The second one could be phrased as “The user wants to define mocks that only apply to certain modules.” It's an implementation detail that the modules to apply the mocks to are all contained within a particular thread. I won’t propose solutions to this one here but my point is just that worker threads are only one way to approach this.
This is something we should allow, unless there’s some technical reason why it’s unachievable. |
Given that this broke people, I think a revert and a second attempt at fixing the bug is most appropriate. If nothing else, revert in the release branch if we want to keep working on this in the main branch. |
A revert trades one bug for another. The intended behavior of calling But that’s not what was happening before #52706: before that PR, calling I agree that the process hanging is a much worse bug than the hooks applying only to one thread instead of all threads. But the options aren’t to either just revert or not, choosing one bug or the other bug; there’s another change that we should be able to land before the next release: just throw an exception if |
As requested, I have opened another issue with a feature request to describe our use case for allowing worker threads to specify custom loader hooks. It is important to note that the current change in #52706 is not backward compatible. In previous versions, the ESM loader specified on the main process did not propagate to child workers. Consequently, from a maintenance perspective, tools now need two methods to use ESM custom loaders with thread workers and must support Node.js LTS and Active versions. TL;DR: It would be ideal if thread workers could specify additional ESM loader hooks. We the Angular team rely on this specific behaviour. |
As an additional data point, #52706 broke using the |
I understand that, but that's also exactly what this PR did as well and our priority/emphasis has always been on avoiding new breaks to existing code. If there is an alternative fix that can be agreed on quickly then ok, let's see that PR. If that PR is going to take some time to work up, then the right thing to do is revert until the corrected solution can be implemented. |
It looks like we have one: #53200 |
c6ebeb5
to
6cea493
Compare
please keep the two commits when landing because one is a spurious formatting change needed to make the lining CI happy (no idea why it shows up in this specific PR). |
This comment was marked as outdated.
This comment was marked as outdated.
Why keep them separate? It seems better to squash. I think we are in a case where the initial code was not linter-compliant but was just never changed since the linter was introduced or updated (we only lint modified files). |
Ok |
This comment was marked as outdated.
This comment was marked as outdated.
I'll open the revert revert PR tomorrow. |
Landed in 8c5c2c1 |
Is there a benefit to opening and landing a revert-revert if it can’t get released? Maybe we should just rebase #53200 on top of the commits from this branch, and then whenever that PR lands it can go out in a release? Then there’s no potential confusion for releasers, of needing to be aware that a particular commit (the revert-revert) should never get released without the follow-up that fixes its bug. |
@GeoffreyBooth I agree. If #53200 or my future PR (or both) will land this is by far the easiest way. |
This reverts commit 22cb99d. PR-URL: nodejs#53183 Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Gerhard Stöbich <deb2001-github@yahoo.de>
This reverts commit 22cb99d. PR-URL: nodejs#53183 Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Gerhard Stöbich <deb2001-github@yahoo.de>
This reverts commit 22cb99d.
Given #53182 and #53097, it's better to revert this to fix the regressions instead. Note that the application is deadlocking when using
register()
within a worker thread.Note that #52706 did not mention any of the limitations introduced by the change in OP.
This important change was only mentioned in the code and some internal discussionsz:
https://github.com/nodejs/node/pull/52706/files#diff-c7f1002d283d353145656887966dfbdd0ea26e13e398b21023d093c6248feaddR8.