groundwater / federation

A Federated Message Network in Node.js
http://underflow.ca/federation
59 stars 5 forks source link

Awesome Picard Meme

Introduction

Federation is a federated message network for distributed environments

Federation is inspired by Akka and Erlang, and borrows some semantics from the actor model. While there are actors, many features familiar to Akka and Erlang are not included. Federation prioritizes being useful to the Node.js community over being faithful to the pure actor model.

Federation considers cross-process and cross-host messaging to be the top priority. It has been designed to sit above an application protocol like axon or http, and can be extended to any other protocol quite easily.

Contributors

A good module evolves to meet the needs of the community. There are many ways you can help. Pull-requests are always welcome, but you don't have to be a programming expert to lend a hand.

  1. ask a question about using federation, your question may help others
  2. suggest an enhancement, suggestions can help prioritize features
  3. tell us your success stories, how have you used federation, and what tips do you have for others?

Install

$ npm install federation

Usage

Every actor has a name, and can receive messages at that name.

var director = require('federation').init().director;

var actorBob = director.createActor('bob');
var actorTom = director.createActor('tom');

Send a Message

Federation nodes can send and receive messages to each other. Actors tell each other messages with:

actorBob.tell('tom','Good Morning');

Telling a message is a fire-and-forget approach.

Receive Messages

Actors receive messages by binding a callback to their onMessage property:

actorTom.onMessage = function(message){
  console.log('Got Message:', message);
}

The callback will be invoked as a method, so this resolves to the actor object.

actorTom.onMessage = function(message){
  this.tell('joe','Got Message!');
}

Request-Reply Pattern

Actors can also ask other actors questions that will receive replies.

actorBob.ask('tom','Are you happy?',function(err,happy){
  if(err) return console.log('Error Asking Tom:',err);
  if(happy){
    console.log('Tom is Happy');
  }else{
    console.log('Tom is Not Happy');
  }
});

The request-reply pattern uses anonymous actors known as extras. An extra has a limited life span of 5000 by default. If the timeout occurs before a reply is delivered, a TIMEOUT error will be send to your callback.

Routing

Federation supports inter-process communication, and abstracts the details away from the programmer.

Actors have names, any name you like. The nameing convention is up to you, but choosing a good convention will make routing easier. Each process has its own router and routing table. Since messages are addressed to other actors by name, the router matches names to URLs. Once a match is found, the message is sent to the remote process.

Routing

Routers have a default local route. Any message matching the default route will be delivered locally. Additional routes can be defined in a JSON-encoded routes file:

[
  {
    "regex": "hadoop/.*",
    "address": "axon://10.0.1.12/"
  },
  {
    "regex": "mongo/.*",
    "address": "axon://10.0.1.122/"
  }
]

Incoming messages are matched in-order against the regex key. The first match wins, and the packet is forwarded to the gateway at the destination address. The default route will always be matched last.

The easiest way to add a routes file is by setting the table_file key:

var federation = require('federation');
federation.defaults.table_file = process.env.ROUTES_FILE_PATH;
var director = federation.init().director;

See the example in Multi-Proc Example for two-process routing table. Routes can be the same, or different hosts.

Documentation

Comprehensive documentation is kept in the wiki.

The wiki is open to anyone for improvement. Feel free to make constructive edits. If you are not sure about making a change, please ask first on the issue tracker.

Todo

The todo list is maintained under the issue tracker

License

Copyright (c) 2013 Jacob Groundwater (groundwater@gmail.com)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.