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

hubiquitus-core

v0.10.2

Published

Actor model for Hubiquitus

Downloads

273

Readme

Build Status

Hubiquitus

Hubiquitus core system. Actor oriented framework massively distributed.

Quick start

Create a new folder and run command :

$ npm install hubiquitus-core

Then create an index.js file and put inside :

var hubiquitus = require('hubiquitus-core');
var logger = hubiquitus.logger('pingpong');
hubiquitus.logger.enable('pingpong');

hubiquitus
  .addActor('hello', function (req) {
    logger.info('Hello World !');
  })
  .start()
  .send('tmp', 'hello');

This code does the following :

  1. Imports hubiquitus library
  2. Creates a logger with the namespace "pingpong"
  3. Enables that logger; note that : - loggers are disabled by default - logger enabling function can take the minimum log level as a second argument - log levels are, in order : trace, debug, info, warn, error|err
  4. Creates a "hello" actor that just logs "Hello World !"
  5. Starts the hubiquitus system
  6. Sends a message to the hello actor using a "fake" tmp actor id : the hello actor will receive the message from tmp.

Run the sample with command :

$ node index.js

The container will run until you stop the node process. You can kill it with CTRL+C.

Concepts

Actor

An actor is just a piece of code with an id. When a message is sent to this id, the code is executed. Inside an actor code, you have access to :

  • this.id is the actor id
  • this.send is a send function taking four arguments : the target actor id, a content, a timeout (optional) and a response callback (optional)

And actor id (or aid) has a specific format : [identifier]/[resource]

The identifier is also called bare id.

Example : hello/de3ef8f1-28f1-4548-95d2-304b70bd01d9 is a full aid

  • hello is the bare id.
  • de3ef8f1-28f1-4548-95d2-304b70bd01d9 is the resource

The resource is an UUID (unique identifier) generated automatically and added to the bare id of an actor when it is added to a container.

When sending a message, the target can be a full aid, or a bare id. If the target is a bare id, the system will select an existing actor with a matching full id to process the message to.

Container

A container is a group of actors. Hubiquitus is a singleton obtained when requiring the hubiquitus-core module. Thus, there can be only one container in a node process.

Discovery

The discovery is the process used so that containers can talk to eachother.

Ping-pong sample

Let's make a "ping-pong" discussion between two Hubiquitus actors.

var hubiquitus = require('hubiquitus-core');
var logger = hubiquitus.logger('pingpong');
hubiquitus.logger.enable('pingpong');

hubiquitus
  .addActor('ping', ping)
  .addActor('pong', pong)
  .start()
  .send('pong', 'ping', 'PONG');

function ping(req) {
  logger.info(this.id + '> from ' + req.from + ' : ' + req.content);

  var _this = this;
  setTimeout(function () {
    _this.send(req.from, 'PING');
  }, 1000);
}

function pong(req) {
  logger.info(this.id + '> from ' + req.from + ' : ' + req.content);

  var _this = this;
  setTimeout(function () {
    _this.send(req.from, 'PONG');
  }, 1000);
}

This code does the following :

  1. Creates two actors named ping and pong
  2. Starts the container
  3. Initiates the dialog between ping and pong by sending a message to ping, from pong

Now let's have the ping actor count messages. To do this, we are going to specify a scope when creating the actor. See the code, it's pretty self-explanatory.

var hubiquitus = require('hubiquitus-core');
var logger = hubiquitus.logger('pingpong');
hubiquitus.logger.enable('pingpong');

hubiquitus
  .addActor('ping', ping, {count: 0})
  .addActor('pong', pong)
  .start()
  .send('pong', 'ping', 'PONG');

function ping(req) {
  this.count++;
  logger.info(this.id + '> from ' + req.from + ' : ' + req.content = ' [' + this.count + ']');

  var _this = this;
  setTimeout(function () {
    _this.send(req.from, 'PING');
  }, 1000);
}

function pong(req) {
  logger.info(this.id + '> from ' + req.from + ' : ' + req.content);

  var _this = this;
  setTimeout(function () {
    _this.send(req.from, 'PONG');
  }, 1000);
}

Note that when specifying a scope, id, send, onMessage and scope are reserved by the system.

Hubiquitus API

Here are the available methods on the Hubiquitus container.

start(options)

The start method can be called at any time. Messages sent while hubiquitus isnt started are queued.

Parameters :

|Parameter| Type |Description|Mandatory| |:-----------:|:--------:|:-------------:|:-----------:| | options | Object | Options | No |

Available options :

  • discoveryAddr {String}
  • discoveryPort {Number}
  • ip {String}
  • podAddrs {String[]}
  • podDiscoveryPort {Number}

Typical usage :

  • multicast discovery :
  • discoveryAddr
  • ip

Example :

var hubiquitus = require('hubiquitus-core');
hubiquitus.start({
  discoveryAddr: 'udp://224.0.0.1:5555'
});

stop()

Stops the Hubiquitus container.

addActor(aid, onMessage[, scope])

Adds an actor to the container.

Parameters :

|Parameter| Type | Description |Mandatory| |:-----------:|:--------:|:---------------------:|:-----------:| | aid | String | Receiver aid | Yes | | from | String | Actor aid | Yes | | onMessage | Function | on message behaviour | Yes | | scope | Object | Actor scope | No |

The onMessage function is the behaviour executed when receiving a message. It takes a req Object as an unique parameter :

  • from {String} is the sender aid
  • to {String} is the receiver aid
  • content {*} is the content of the message
  • timeout {Number} is the maximum delay for delivering the message
  • date {Date} is the send date of the message
  • reply {Function} is a function to call to reply to the message

The reply function takes two arguments :

  • err {*} is the optional error
  • content {*} is the response content

Example :

var hubiquitus = require('hubiquitus-core');

hubiquitus
  .addActor('ping', function (req) {
    this.count++;
    req.reply(null, 'pong');
  }, {count: 0});
  .start();

removeActor(aid)

Removes an actor from the container.

Parameters :

|Parameter| Type | Description |Mandatory| |:-----------:|:--------:|:-----------------:|:-----------:| | aid | String | Actor aid | Yes |

send(to, from, [content, timeout, cb])

Sends a message from an actor to another.

Parameters :

|Parameter| Type | Description |Mandatory| |:-----------:|:--------:|:-----------------:|:-----------:| | to | String | Receiver aid | Yes | | from | String | Sender aid | Yes | | content | Object | Message content | No | | cb | Function | Response callback | No |

The cb function is the behaviour executed when receiving the message response : It takes a two arguments :

  • err {*} is the optional error
  • res {Object} is the response message.

A res message is similar to a req message. It contains :

  • from {String} is the sender aid
  • to {String} is the receiver aid
  • content {*} is the content of the message
  • timeout {Number} is the maximum delay for delivering the message
  • date {Date} is the send date of the message

Example :

var hubiquitus = require('hubiquitus-core');

hubiquitus
  .addActor('Asriel', asriel)
  .addActor('Marisa', marisa)
  .send('Metatron', 'Marisa', 'Greets Asriel for me!')
  .start();

function asriel(req) {
  console.log('Asriel> from ' + hubiquitus.utils.aid.bare(req.from) + ' : ' + req.content);
  req.reply(null, '...');
}

function marisa(req) {
  console.log('Marisa> from ' + hubiquitus.utils.aid.bare(req.from) + ' : ' + req.content);
  this.send('Asriel', 'Hello from Metatron !', function (err, res) {
    console.log('Marisa> response from ' + hubiquitus.utils.aid.bare(res.from) + ' : ' + res.content);
  });
}
  • A "fake" Metatron actor sends a message to Marisa
  • Marisa sends a message to Asriel
  • Asriel replies to Marisa

use(function)

Adds a middleware to use. The defined function will be executed each time an incoming request comes in or an outcoming request comes out.

Parameters :

|Parameter| Type | Description |Mandatory| |:-----------:|:--------:|:-----------------:|:-----------:| | function | Function |Middleware function| Yes |

The middleware function takes three parameters :

  • type : message type. Is a String, four possibilities :

  • req_out : the message is an outcoming request

  • req_in : the message is an incoming request

  • res_out : the message is an outcoming response

  • res_in : the message is an incoming response

  • msg : transiting message (is a request or a response, depending on the type)

  • next : callback to call at the end of the process (to call the next middleware)

Example :

var hubiquitus = require('hubiquitus-core');
hubiquitus
  .addActor('B', function (req) {
    logger.info('Hello World !');
  })
  .start()
  .use(function (type, msg, next) {
    var fromAid = hubiquitus.utils.aid.bare(msg.from);
    var toAid = hubiquitus.utils.aid.bare(msg.to);
    switch (type) {
      case 'req_out':
        console.log('[outcoming request from ' + fromAid + ' to ' + toAid + ' !]');
        break;
      case 'req_in':
        console.log('[incoming request from ' + fromAid + ' to ' + toAid + ' !]');
        break;
      case 'res_out':
        console.log('[outcoming response from ' + fromAid + ' to ' + toAid + ' !]');
        break;
      case 'res_in':
        console.log('[incoming response from ' + fromAid + ' to ' + toAid + ' !]');
        break;
    }
    next();
  })
  .send('A', 'B');

In the above example, an A actor sends a message to a B actor inside the same container. The middleware function is executed twice and displays :

[outcoming request from A to B !]
[incoming request from A to B !]

Note that you can start using a middleware after the hubiquitus container has started.

set(key, value)

Sets a hubiquitus property.

Parameters :

|Parameter| Type |Description |Mandatory| |:-----------:|:--------:|:--------------:|:-----------:| | key | String | Property key | Yes | | value | * | Property value | Yes |

Samples

Samples list :

  • pingpong : simple actor based ping-pong
  • ping : ping between two "instances" of the same actor
  • ping-cs : coffeescript version of ping
  • ping-remote : ping between two foreign actors (two different containers)
  • request-reply : simple request-reply sample
  • middlewares : middlewares demo

Docs

Under heavy developments. The whole documentation of the Hubiquitus project is available in the docs subdirectory of this repo.

License

Hubiquitus is a free and open source software licensed under the terms of the MIT license.

This document itself, as the whole documentation provided with the project, is licensed under the terms of the Creative Commons Attribution Unported 3.0 (CC BY 3.0).