npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

mob

v0.0.9

Published

simple multi-process applications

Downloads

218

Readme

mob

A simple toolkit for parallelizing node.js apps over several processes, built on top of the cluster module.

$ npm install mob

usage

A mob-based app runs as two or more processes - the Kingpin (master), and one or more Mobsters (workers).

The Kingpin's only function is to keep the cluster running by launching and reviving children, and to route messages between them. It should contain no application logic whatsoever, which is to ensure that bugs in your app don't end up crashing your server, but just temporarily break the affected child process.

Mobsters are the actual workers that run your application logic. Mobsters have different roles, so the application breaks down in several worker types, each of which specializes in different functionality, and exports it to the cluster just like a CommonJS module exports its API.

The main script will look like this:

main.js


require('mob')
  .start('myapp') //  starts the app and sets the process.title prefix for all processes.
  .base(module)   //  optional, all roles will have their paths resolved relatively to this module.

  //  .role() accepts three parameters:
  //  - the name of the role to be used with `mob.require()`;
  //  - the module to require in child processes assigned with this role;
  //  - any options, currently only the number of worker processes to spin up and keep alive.

    .role('back',  "./background-worker.js", {workers: 4})
    .role('front', "./http-server.js", {workers: 2});

$ node main will launch this script in as a Kingpin, which in turn will launch the 6 specialized child processes, in this case 4 background workers and 2 frontend processes.

background-worker.js


console.log('Background worker ' + process.pid + ' running.' );

exports.foo = function () {
  console.log('Bar! My pid is ' + process.pid);
};

http-server.js


var mob = require('mob');

//  Get a remoting proxy to the 'back' role's interface.
var back = mob.require('back');

//  Because mob is based on cluster,
//  all 2 'http-server' processes share the same server handle:

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');

  console.log('Server ' + process.pid + ' served an http request.');

  //  This will call foo on any one of the 4 'back' processes.
  back.foo();

  //  The proxy load-balances between all 4 processes, so
  //    next time `back.foo();` gets called it might hit a different process.

}).listen(1337, "127.0.0.1");
console.log('Server ' + process.pid + ' running at http://127.0.0.1:1337/');

mobsters!

exchanging messages

mob.require() is built on a very simple message-exchange mechanism powered by process.send() and worker.send(). This mechanism is also exposed to application code in Mobster processes.

To send a message to all processes, do:

require('mob')
    .send( myobj );

To send a message to all back processes, you could:

require('mob')
    .all('back').send( myobj );

To send a message to a random back process:

require('mob')
    .any('back').send( myobj );

Finally, to target a particular process by pid, do:

require('mob')
    .pid( somepid ).send( myobj );

To listen for messages:

require('mob').on('message', handler);

Keep in mind that messages are passed around as JSON, so this is only good for exchaning data.

mobster export proxies

mob.require() is not require() - you are not dealing with the module.exports object directly, but with a proxy. Only functions are proxied, any other exported properties are ignored.

Mobster proxies created with mob.require() load-balance between workers, which means Mobsters' exports are only good if they are stateless. If you want to reuse state, for example because you're using an in-process key/value store like node-dirty or divan, you should extract it in its own Mobster with only one worker.

passing callbacks

The mob.require() facility supports exchanging callbacks between processes, but two major limitations apply.

First, currently a callback can be invoked only once, after which it is de-referenced and any further messages pushing data to that callback will be ignored.

Also, make sure you do call back, or else you will leak memory, as each callback is retained locally in the calling process and transported over to the other process as a numeric ID - and if you do not call back, this hard reference currently does not get collected.

license

MIT.