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

MicroServices

v0.0.7

Published

a microservice architecture ready to use. Just use heritage on workers.

Downloads

12

Readme

MicroServices.js

MicroServices.js is a minimum implementation of a micro service architecture, based on Node.js and RabbitMQ. Every service is communicating throw the RabbitMQ broker.

Dependencies

  • Rabbit.js. RabbitMQ is not include. You need to install it.
  • cli-color used for logger color.

Architecture overview

Architecture

Components

  1. SystemManager
  2. RabbitMQ Bus
  3. Workers

Global behavior

I advice to launch the bus and then the SystemManager, and after that the workers. Globally speaking, workers are communicating with each other via the bus and specific messages. The first thing they do is to declare themselves to the SystemManager and the other workers of the same type. Then, they share messages via the bus. The principal messages is to ask for another worker to do a job. In my example, the REST worker receive the external message, send it to the Pilot worker who will know what to do with it. He can ask for the DB worker to store an information and the say ok to the client via the REST worker.

Roles

  • SystemManager's aim is to controls what happens on the bus. He stores the list of workers available. He can answer to a worker asking for a job by sending an error if there's no worker of the good type available. He can provide the list of the workers on the bus.
  • Worker's aim is to perform a dedicated work. DB worker can connect to a DB, REST worker can answer REST requests. You can extend worker to do whatever you want.

Communications

Workers present them selves on the network by send a message on the channel "notifications", on the topic "worker.new". It allows the SystemManager and the other worker to discover it. By now, this message looks like this: {"id":"WB:1460306476102","type":"WB"}

id is the ID of the worker. Currently, it is composed of the type of the worker and the timestamp of creation of the worker.

When a worker shut down, it send a message on the bus to delete the worker from the list. It is the same message, except that it is sent on the topic: worker.del.

As, the SystemManager can be launch after the workers, it can get the list of all workers, by sending a message on the worker.getAll topic. The workers, send the same message than when they arrive on the network.

System configuration

The only configuration mandatory is the RabbitMQ connection URL. It is stored in the config/config.json file. You can add a keepalive key that allow the SystemManager to regularly ask for Workers list. If 0 or no entry, the keepalive is not done. For performance purpose, you can activate binary exchanges on the bus. See data_transfer_protocol.

/**
* Config file for every worker 
* contains the information to connect to the broker
* broker_url: url of the broker system. Here RabbitMQ
* keepalive: frequency of keepalive made by SystemManager
* SystemManager_log: activate SystemManager logging
* Worker_log: activate Worker logging
* data_transfer_protocol: data compression type on the bus. 
*         Supported: JSON/BSON/MessagePack
* 
**/ 
{
"broker_url": "amqp://localhost",
"keepalive": 1000,
"SystemManager_log": true,
    "Worker_log": true,
    "data_transfer_protocol": "msgpack"
}

Ack and retry

When a job is sent, the worker that take it have to send an ack. If no worker does, the job is resend every 2s until it is taken or the SystemManager says that there's no worker of the good type. If an ack is receive by the sender for a job he sent, he remove it from the list of pending jobs.

Create your own system

To create your own system you have to inherit a dedicated com from the Worker class Here an example of a DB Worker

// Child class of Worker dedicated to DB connection
var Worker = require("./Worker.js");
var logger = require("./logger.js");

var DBW = new Worker("WB");
DBW.treatError = function(error) {
        logger. log("MicroService", "Worker B - DB connector", "Error received");
}

DBW.storeInDB = function(data) {
        // DO Whatever
}

DBW.getFromDB = function() {
        // DO Whatever
}

logger.js is a logger function to log on the console with colored syntax

TODO

Manage bus connection issues on both workers and SystemManager.

Example

In the example, you can find a REST Worker, accepting connexion on port 8080. If http method is not post or get, or if path is different from /movies/, it will responde 404. Else, it will send a message to the Pilot Worker to treat the customer request. The Pilot will ask the DB Worker to store or retrieve the data and send it back to the REST Worker. Finally, the REST Worker responde the client. If an error occurs, the REST Worker will answer with HTTP 500 code.

Tests

Tests are build with Mocha, Should and Istanbul for test coverage. By now, test coverage is:

  • Workers: 93,9%
  • SystemManager: 94,9%

Tested with the 3 workers in example directory and a bus on AWS EC2 micro instances. Response time < 90ms.

Release note:

  • 0.0.5: Update Worker id, so that you can now etheir send a job a any worker of the good type, or to a specific worker.
    • To send a job to any worker, send to Worker_type:*
    • To send a job to a specific worker send to worker id

Here is a sample of code:

// "Stuff to do" will be sent to any worker of type WD
Worker.sendToNextWorker(["WD:*"], {data: "Stuff to do"});
// "Stuff to do" will be sent to worker of type WD with id WA:1461679731775
Worker.sendToNextWorker(["WD:1461679731775"], {data: "Stuff to do"});
  

Written with StackEdit.