Skip to content

Commit

Permalink
sort docs into different categories
Browse files Browse the repository at this point in the history
  • Loading branch information
Akamaozu committed May 7, 2018
1 parent ff8368c commit 7a7a581
Show file tree
Hide file tree
Showing 8 changed files with 287 additions and 232 deletions.
252 changes: 20 additions & 232 deletions README.md
@@ -1,250 +1,38 @@
# Supe

# Fault-Tolerance Framework for Node.js Apps
## Fault-Tolerant Node.js Programs

[![npm version](https://badge.fury.io/js/supe.svg)](https://badge.fury.io/js/supe) [![travis ci](https://travis-ci.org/Akamaozu/node-supe.svg?branch=master)](https://travis-ci.org/Akamaozu/node-supe) [![Coverage Status](https://coveralls.io/repos/github/Akamaozu/node-supe/badge.svg?branch=master)](https://coveralls.io/github/Akamaozu/node-supe?branch=master)

# Intro

## Why You Should Care About Fault Tolerance

Your coworkers, mentors and heroes write faulty code. **You** write faulty code.

JavaScript isn’t particularly forgiving when code fails, so your app rolls over and stays dead. While we have many tools for bringing a dead Node.js app back to life, we typically don’t structure them in ways that limit the problem's impact on the app.

**Fault Tolerance reduces the impact problems have on your app**. At worst you’ll have a bottleneck in a component, but it won’t bring everything else to a grinding halt, or worse yet, send it to the big farm in the cloud.

## Why You Should Try A Framework for Fault Tolerance
Node.js makes it easy (and quick) to write a useful program.

You definitely don’t need one but a framework makes it **really easy to start** making things more fault-tolerant while providing **a common platform for building, sharing ideas and tools** the same way Express.js does for writing web servers.
**Unfortunately, there's only so much you can do in one event loop before things start stepping on each other's toes**. It only takes one slow/busy component to bring the rest of the program to its knees.

## How Supe Can Help
**Supe is a two-pronged approach to writing safer Node.js programs**:
1. Make it easy to put parts of your program into private Node.js instances.
2. Provide tools that make working with multiple Node.js instances a breeze.

While making your app more fault-tolerance is very rewarding, it is a VERY HARD THING™.
**The resultant program is safer because faults are isolated on a per-component basis, and likely faster because it utilizes multiple event loops**.

- You need ways to communicate between formerly-cozy components.
- Each component now outputs data to a different stdout.
- Even though each component is still single-threaded, your overall application is now multi-threaded.

This is just the tip of the iceberg of concerns introduced by trying to be fault-tolerance.

Supe helps by providing good default solutions for these problems and allows you to modify (or overwrite) any particular one so you can implement the solution that works best for your specific challenge.
![Multiple Node.js instances working together](http://public.designbymobi.us/img/node-satellite-error.jpg)
Output from [TorontoJS Workshop Satellite](https://github.com/Akamaozu/workshop-satellite).

# Install
```js
npm install --save supe
```

# Getting Started

## Supervisors and Citizens

The first step to fault-tolerance is breaking your app into separate parts.

For example, instead of one file with multiple responsibilities like:

```js
// inside app.js
var http = express(),
db = db_driver(),
ws = websocket();
```

We're moving towards separate programs with individual responsibilities and the app becomes their manager / coordinator.

```js
// inside app.js
var http = supervisor.start( 'http', 'http.js' ),
db = supervisor.start( 'db', 'db-driver.js'),
ws = supervisor.start( 'ws', 'websocket.js');
```

Supe refers to the manager / coordinator as a supervisor; the components are called citizens.

## Setup Supervisor

### Create
```js
var supervisor = require('supe')();
```

### Supervise Citizens
```js
// supervise server.js
supervisor.register( 'server', 'server.js' );
supervisor.start( 'server ');

// or
supervisor.start( 'server', 'server.js' );

// supervisor will restart server.js whenever it crashes
```

## Basic Supervisor Config

### Set Citizen Overcrash

NOTE: Supe will stop reviving a citizen after it crashes excessively.

```js
var supervisor = require('supe')(),
server = supervisor.start( 'server', 'server.js', { retries: 3, duration: 3 });

// if server.js crashes more than three times in three minutes, supe considers it overcrashed
```

### Set Default Overcrash

```js
var supervisor = require('supe')({ retries: 3, duration: 3 }),
server = supervisor.start( 'server', 'server.js' ),
worker = supervisor.start( 'worker', 'worker.js' );

// all supervised scripts will use the default overcrash thresholds
// individual overcrash thresholds override defaults

var worker2 = supervisor.start( 'worker2', 'worker.js', { retries: 20 }),
worker3 = supervisor.start( 'worker3', 'worker.js', { duration: 1 });
```

## Supervisor Core API

## Citizen Core API

## Core Components

### Noticeboard

#### About
Supe uses [cjs-noticeboard](https://www.npmjs.com/package/cjs-noticeboard "cjs-noticeboard on npm") to send out notices when certain actions happen. This makes it easy to extend Supe to build custom behavior for your supervisor.

All you need to do is watch a relevant notice and your code will be executed every time a notice is sent out.

#### Watch a Notice

Example:
```js
// tell pagerduty component to send alert when component crashes excessively
supervisor.noticeboard.watch( 'citizen-excessive-crash', 'send-pagerduty-alert', function( msg ){

var data = msg.notice,
citizen = data.name,
pagerduty = supervisor.get( 'pagerduty' );

pagerduty.mail.send({
action: 'send-alert',
message: citizen + ' crashed excessively at ' + Date()
});
});
```

#### More About Notices

### Mail

#### About
Mail is a simple yet reliable way to communicate between components. With a few lines of code, you can send some data to a citizen. When the citizen starts receiving data, hopefully they'll know what to do with what you sent.

Mail is more reliable than notices because they are stored on the supervisor regardless of citizen's state. When the citizen is ready to receive mail, they're sent in the same order they were received by the supervisor.

#### Send

```js
// inside citizen
var supe = require('supe');

// to supervisor
supe.mail.send( 'hello supervisor' );

// to other citizen
supe.mail.send({ to: 'worker-two' }, 'hello worker two' );
```

#### Receive

```js
// inside citizen

var supe = require('supe');

supe.mail.receive( function( envelope, ack ){

var sender = envelope.from,
content = envelope.msg;

console.log( 'message from ' + sender + ': ' + content );

ack();
});
```

Messages don't have to be strings.

```js
// inside server.js

supe.mail.send({ key: 'concurrent-users', value: 9001 });
```

Supervised scripts are given one message at a time.

No more messages will be sent til the current one is acknowledged ( ack() ).

Once you acknowledge a message, the next message is automatically sent.

```js
// worker one

for( var x = 1; x <= 100; x += 1 ){
supe.mail.send({ to: 'worker3' }, x );
}

// worker two

for( var x = 100; x >= 1; x -= 1 ){
supe.mail.send({ to: 'worker3' }, x );
}

// worker three

supe.mail.receive( function( envelope, ack ){

var sender = envelope.from,
content = envelope.msg;

console.log( sender + ' says: ' + content );
ack();
});

// worker1 says 1
// worker2 says 100
// worker1 says 2
// worker2 says 99
// worker1 says 3
// worker2 says 98
// worker1 says 4
// worker2 says 97
```

#### More About Mail

### Supervised Supervisors

Supervised scripts can supervise other scripts.

```js
// inside supervisor.js

var supervisor = require('supe')();

supervisor.start( 'worker', 'worker.js' );
# [Why Supe](docs/why.md)
A few reasons why you should use Supe.

// inside worker.js
# [Getting Started](docs/getting-started.md)
Handy guide to help you quickly get started with Supe.

var supe = require('supe'),
supervisor = supe();
# [Core Components](docs/core-components.md)
The pieces that make up Supe's core and how to use them.

supervisor.start( 'subworker', 'sub-worker.js' );
# Add-ons
An easy way to get more out of Supe is using (or creating + sharing your own) Supe add-ons.

if( supe.supervised ) supe.mail.send( 'started a subworker' );
```
Some examples:
- [Supervisor Add-On: Log Citizen Output](https://github.com/Akamaozu/supe-addon-log-citizen-output)
- [Supervisor Add-On: Log Citizen Lifecycle](https://github.com/Akamaozu/supe-addon-log-citizen-lifecycle)
43 changes: 43 additions & 0 deletions docs/api.md
@@ -0,0 +1,43 @@
# [Supe](../README.md) > API

## Supervisor

### Create Supervisor
```js
var supervisor = require('supe')();
```

### Supervise Citizens
Supervise a citizen by registering and starting it. The supervisor will restart server.js whenever it crashes.
```js
supervisor.register( 'server', 'server.js' );
supervisor.start( 'server ');

// or
supervisor.start( 'server', 'server.js' );
```

### Set Citizen's Overcrash

NOTE: Supe will stop reviving a citizen after it crashes excessively.

```js
var supervisor = require('supe')(),
server = supervisor.start( 'server', 'server.js', { retries: 3, duration: 1 });

// if server.js crashes more than three times in one minute, supe considers it overcrashed
```

### Set Default Overcrash

```js
var supervisor = require('supe')({ retries: 3, duration: 1 }),
server = supervisor.start( 'server', 'server.js' ),
worker = supervisor.start( 'worker', 'worker.js' );

// all supervised scripts will use the default overcrash thresholds
// individual overcrash thresholds override defaults

var worker2 = supervisor.start( 'worker2', 'worker.js', { retries: 20 }),
worker3 = supervisor.start( 'worker3', 'worker.js', { duration: 1 });
```
7 changes: 7 additions & 0 deletions docs/core-components.md
@@ -0,0 +1,7 @@
# [Supe](../README.md) > Core Components

## [Noticeboard](core-components/noticeboard.md)
## [Mail](core-components/mail.md)
## [Supervision](core-components/supervision.md)
## Signal
## Hook

0 comments on commit 7a7a581

Please sign in to comment.