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.
Fixes#10073, per
https://github.com/meteor/meteor/issues/10073#issuecomment-405290391
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.
https://github.com/meteor/meteor/pull/10055#discussion_r201855997
As I explained in this comment, Package._on(packageName, callback) was a
bad API because it never called the callback if the package was not
installed, which caused any app not using the autoupdate package to get
stuck trying to communicate with the autoupdate package.
Without the `--phantom` flag passed to the `meteor self-test` command, the
client tests within those self-test test definitions will only be run on
Chrome Headless.
We might want to consider making it the default, so it runs without an
additional argument on local development as well, but this will make sure
that these important Phantom tests run in CircleCI to ensure we're testing
both modern and legacy browsers (of which the later group includes
PhantomJS, in all its "legacy" glory).
cc @hwillson @benjamn for input.
Instead of having every message consumer listen to every message and act
on the ones that seem relevant to its interests, we now have a single
process.on("message", callback) hook that can dispatch messages to
different Meteor packages running in the server process.
Receiving packages should export an onMessage function. The onMessage
function may be async, and its result will be delivered back to the build
process as the result of the sendMessage Promise.
This package is already importable because it's a dependency of request,
npm, and http-signature, but it's a good idea to depend on it explicitly
just in case those packages stop depending on it in the future.