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
Use listener API for communication between build/server processes. #10077
Conversation
// package, one after the last. The first message waits for the | ||
// package to call Package._define(packageName, exports). | ||
promises[packageName] = ( | ||
promises[packageName] || Package._promise(packageName) |
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.
Since we're no longer using Package._promise
in core, and it was only recently introduced for this (now removed) code, I think we should remove it for the sake of keeping the APIs exposed by the core meteor
package as small as possible.
}); | ||
// If arch is not a string, the receiver of this message should | ||
// assume all clients need to be refreshed. | ||
await appProcess.proc.sendMessage("client-refresh"); |
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.
If the autoupdate
package is not installed, no message will be delivered to that package, so no error needs to be caught here.
// autoupdate package. | ||
Object.keys(cachesByPlatform).forEach(platform => { | ||
delete cachesByPlatform[platform]; | ||
}); |
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.
This is the part of the PR that actually fixes #10073.
Fixes #10073, per #10073 (comment) While thinking about this bug, I realized that sending IPC messages to specific packages in the server process was much less flexible than sending messages based on an arbitrary topic string, since the topic string approach allows both `autoupdate` and `dynamic-import` to listen for the same message. The topic string approach calls for a listener interface like `onMessage(topic, callback)`, which elegantly replaces the previous approach of requiring packages to export a single `onMessage` function. However, because the `meteor` package does not have access to the module system, implementing the `onMessage` listener interface in the `meteor` package would have required exposing an API like `Meteor.onMessage(topic, callback)`, which has an unpleasant global smell to it. Instead, the `onMessage` function should be explicitly imported (using the module system) from a less-generically-named package. Since I knew I was going to have to move the message dispatch logic out of the `meteor` package, I decided to create a new package called `inter-process-messaging` to implement the parent/child components of the IPC system.
0c0a1e6
to
2450ffe
Compare
const results = []; | ||
const callbacks = callbacksByTopic.get(topic); | ||
if (callbacks && callbacks.size > 0) { | ||
callbacks.forEach(cb => results.push(cb(payload))); |
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.
One really nice benefit of using Set#forEach
here is that if you add new elements to the set while you're traversing it, they will be included in the same forEach
loop!
Every process is potentially the child of some other process and the parent of zero or more child processes of its own, so it's confusing to use terminology that always treats the current global.process as a "parent" process, or to include PARENT and CHILD in the message types. Instead, this new implementation uses message types MESSAGE, RESPONSE, PING, and PONG, and refers to `process` and `otherProcess` objects, with the caveat that sometimes `process === otherProcess`, because `process.send` can be used to send messages to the parent process. Instead of relying on the child to send a special CHILD_READY message to the parent when it's ready to receive messages, the sending process polls the receiving process with a preflight PING message, and the receiving process immediately responds with a PONG when ready.
I would like to extract this functionality as an npm package one day, but I think I need to draw the line on this endless refactoring somewhere. |
Fixes #10073, per #10073 (comment)
While thinking about this bug, I realized that sending IPC messages to specific packages in the server process was much less flexible than sending messages based on an arbitrary topic string, since the topic string approach allows both
autoupdate
anddynamic-import
to listen for the same message.The topic string approach calls for a listener interface like
onMessage(topic, callback)
, which elegantly replaces the previous approach of requiring packages to export a singleonMessage
function.However, because the
meteor
package does not have access to the module system, implementing theonMessage
listener interface in themeteor
package would have required exposing an API likeMeteor.onMessage(topic, callback)
, which has an unpleasant global smell to it. Instead, theonMessage
function should be explicitly imported (using the module system) from some less-generically-named package.Since I knew I was going to have to move the message dispatch logic out of the
meteor
package, I decided to create a new package calledinter-process-messaging
to implement the parent/child components of the IPC system.