Enter the Wormhole; IPC goodness

Enter the Wormhole; IPC goodness

This post and the example in it have been updated to match version 1.x.x.

Node’s child_process module allows you to spawn and fork new processes, optionally with a built-in Inter-Process Communication (IPC) channel. This is an easy way to communicate with the child process, and valuable on its own in many situations. But it’s not very developer-friendly.

Wait, scratch that, its very developer-friendly. It’s just not… easily and repeatably usable. You will need to define your own JSON-based protocol, which can become tedious if you need to do this often. Addition: it’s not really necessary to define your own protocol: primitive values can be sent too, albeit without metadata.

So, to stay in keeping with DRY and KISS I decided to make a little module that does most of the heavy lifting for me. Note that there are probably dozens of modules out there that do what I did and probably better, but that doesn’t take the fun out of building it. It’s simple and it works, so I’m sure there are applications.

I wanted a couple of things:

  • A way to notify the other end of the link of events that have happened
  • A way to call commands on the remote end and receive a result back (RPC-like behavior)

To satisfy these requirements I built wormhole. It’s designed to work with Node.JS’s child_process and process, and provides what I was looking for.

Installing it is super simple:

npm i @art-of-coding/wormhole --save

How do you use it, you ask? It’s fairly simple – just fork a child process that uses wormhole, and you can send events and call commands!

In the example below we fork a child process, and both processes use wormhole. This allows them to send events and call remote commands. All features are supported in either direction (it’s bidirectional).

The master process:

const childProcess = require('child_process')
const Wormhole = require('@art-of-coding/wormhole')

const child = childProcess.fork('./my-child.js')
const wormhole = new Wormhole(child)

// Register a `startup` event handler
wormhole.events.on('startup', () => {
  console.log('received startup event!')
})

// Register an `add` command
wormhole.define('add', function (a, b) {
  return a + b
})

// Send the `quit` event to the child
setTimeout(() => wormhole.event('quit'), 5000)

The child process:

const Wormhole = require('@art-of-coding/wormhole')

// Without the `channel` argument, `process` is selected by default
const wormhole = new Wormhole()

// Register a `quit` event handler
wormhole.events.once('quit', () => {
  process.exit(-1)
})

// Send an event
wormhole.event('startup')

// Call a remote command
wormhole.command('add', 5, 6).then(result => {
  console.log(`5 + 6 = ${result}`)
})

As you can see for yourself, using it could not be easier!

You can find wormhole on GitHub or npm.


Leave a Reply

Your email address will not be published. Required fields are marked *