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

IPC helper #900

Closed
ehmicky opened this issue Mar 10, 2024 · 3 comments
Closed

IPC helper #900

ehmicky opened this issue Mar 10, 2024 · 3 comments

Comments

@ehmicky
Copy link
Collaborator

ehmicky commented Mar 10, 2024

Proposal

// main.js
const subprocess = execa('./subprocess.js', {ipc: true});
for await (const message of subprocess.ipc.iterable()) {
  ... // Can use subprocess.send()
}
// subprocess.js
import {ipc} from 'execa';

for await (const message of ipc.iterable()) {
  ... // Can use process.send()
}

Returning (with return or break) from either the current process or the subprocess' loop automatically stops listening to the IPC channel.

The parent loop waits for the subprocess to resolve. Also, it throws if the subprocess promise is rejected.

Rationale

The above provides with a simpler syntax for IPC, using async iterables instead of events.

It also enforces best practices:

Disconnection

Ensures the message event handler is cleaned up to prevent processes hanging, and allows graceful exits.

Otherwise, by default, the subprocess hangs until calling .disconnect(), which users might forget. Many might call process.exit() in the subprocess, but that's a forceful exit which might interrupt ongoing logic.

Error handling

Proper error handling. Errors in message handlers are correctly handled and propagated.

Otherwise, by default, an exception in the message handler in the subprocess would result in an uncaught exception.

Subprocess completion/error

Ensures the subprocess promise is awaited and its errors are propagated.

Usually, if IPC is used, it tends to be during the whole lifetime of the subprocess. I.e. the ipc and subprocess promises overlap and can be combined. subprocess does not need to be awaited if subprocess.ipc is.


What do you think?


Edit: some implementation notes:

  • The loop should iterate using on(subprocess, 'message') under-the-hood.
  • Users use process.send() and subprocess.send() to send messages. We keep those as is.
  • The parent's iterable.return() and iterable.throw() should return a promise that waits for the subprocess to complete.
  • Parent/subprocess initial messages are buffered by Node.js, so we don't need to wait for the subprocess to start.
  • for await processes serially. However, users can achieve parallelism by calling async functions without await, although it would make error handling harder (although not impossible).
@sindresorhus
Copy link
Owner

Sounds useful 👍

@ehmicky
Copy link
Collaborator Author

ehmicky commented May 13, 2024

I was looking into this, and created a new issue at #1053 which would supersede this issue, continuing on the same idea but probably better.

@ehmicky
Copy link
Collaborator Author

ehmicky commented May 16, 2024

Closing in favor of #1053.

@ehmicky ehmicky closed this as completed May 16, 2024
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

No branches or pull requests

2 participants