Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'master' of github.com:visionmedia/axon

  • Loading branch information...
commit c3fc18d660b1dacc4e7fa2447388ecf6b752c30f 2 parents 5f52dce + 8a01cf6
@tj authored
View
203 Readme.md
@@ -11,12 +11,17 @@
- message oriented
- automated reconnection
- light-weight wire protocol
- - light-weight implementation (~300 SLOC)
- supports arbitrary binary message (msgpack, json, BLOBS, etc)
- supports JSON messages out of the box
- - push / pull pattern
- - pub / sub pattern
- - event emitter pattern
+
+## Patterns
+
+ - push / pull
+ - pub / sub
+ - emitter
+ - req / rep
+ - router
+ - dealer
## Push / Pull
@@ -47,7 +52,7 @@ sock.on('message', function(msg){
});
```
-Both `PushSocket`s and `PullSocket`s may `.bind()` or `.connect()`. In the
+Both `PushSocket`s and `PullSocket`s may `.bind()` or `.connect()`. In the
following configuration the push socket is bound and pull "workers" connect
to it to receive work:
@@ -60,7 +65,9 @@ to push results:
## Pub / Sub
-`PubSocket`s send messages to all subscribers without queueing:
+`PubSocket`s send messages to all subscribers without queueing. This is an
+important difference when compared to a `PushSocket`, where the delivery of
+messages will be queued during disconnects and sent again upon the next connection.
```js
var axon = require('axon')
@@ -74,7 +81,7 @@ setInterval(function(){
}, 500);
```
-`SubSocket` provides selective reception of messages from a `PubSocket`:
+`SubSocket` simply recieves any messages from a `PubSocket`:
```js
var axon = require('axon')
@@ -90,8 +97,8 @@ sock.on('message', function(msg){
## EmitterSocket
`EmitterSocket`'s send and receive messages behaving like regular node `EventEmitter`s.
-This is achieved by using pub / sub sockets behind the scenes, automatically assigned
-the "json" codec. Currently we simply define the `EmitterSocket` as a `PubSocket` if you `.bind()`, and `SubSocket` if you `.connect()`, providing the natural API you're used to:
+This is achieved by using pub / sub sockets behind the scenes and automatically formatting
+messsages with the "json" codec. Currently we simply define the `EmitterSocket` as a `PubSocket` if you `.bind()`, and `SubSocket` if you `.connect()`, providing the natural API you're used to:
server.js:
@@ -121,12 +128,143 @@ sock.on('login', function(user){
});
```
+## Req / Rep
+
+`ReqSocket`s send and recieve messages, queueing messages on remote disconnects. There
+is no "lock step" involved, allowing messages sent later to recieve replies prior to
+previously sent messages. `RepSocket`s reply to recieved messages, there is no concept of `send()`. Each
+recieved message will have a `reply` callback, which will send the response back to the remote peer:
+
+client.js
+```js
+var axon = require('../..')
+ , sock = axon.socket('req');
+
+sock.connect(3000);
+
+sock.on('message', function(msg){
+ console.log('got: %s', msg.toString());
+});
+
+setInterval(function(){
+ sock.send('ping');
+}, 150);
+```
+
+server.js
+```js
+
+var axon = require('../..')
+ , sock = axon.socket('rep');
+
+sock.bind(3000);
+
+sock.on('message', function(msg, reply){
+ console.log('got: %s', msg.toString());
+ reply('pong');
+});
+```
+
+## Router
+
+`RouterSocket`s send a message to an "identified" peer using the socket's "identity"
+(see `socket options`). Sent messages are not queued. The message sent leverages
+multipart messages by framing the "identity" first, the delimiter second, and then
+the actual message body.
+
+__Note:__ This will probably change due to the awkwardness of handling your own delimeters.
+
+client.js
+```js
+var axon = require('../..')
+ , sock = axon.socket('router');
+
+sock.bind(3000);
+
+sock.on('message', function(from, delim, msg){
+ console.log(msg.toString());
+});
+
+setInterval(function(){
+ sock.send('foo', '\u0000', 'hello foo');
+ sock.send('bar', '\u0000', 'hello bar');
+}, 150);
+```
+
+server.js
+```js
+var axon = require('../..')
+ , foo = axon.socket('rep')
+ , bar = axon.socket('rep');
+
+foo.set('identity', 'foo');
+foo.connect(3000);
+
+foo.on('message', function(msg, reply){
+ reply('foo: pong');
+});
+
+bar.set('identity', 'bar');
+bar.connect(3000);
+
+bar.on('message', function(msg, reply){
+ reply('bar says: pong');
+});
+```
+
+## Dealer
+
+`DealerSocket`s receive messages and round-robin sent messages. There is no
+correlation between the two. They can be thought of as a `PushSocket` and `PullSocket`
+combined. Here the dealer the serves as an "echo-service", sending whatever is recieves:
+
+dealer.js
+```js
+var axon = require('../..')
+ , sock = axon.socket('dealer');
+
+sock.set('identity', 'echo-service');
+sock.connect(3000);
+
+sock.on('message', function(msg){
+ sock.send(msg);
+});
+```
+
+client.js
+```js
+var axon = require('../..')
+ , sock = axon.socket('router');
+
+sock.bind(3000);
+
+sock.on('message', function(from, msg){
+ console.log('%s said: %s', from.toString(), msg.toString());
+});
+
+setInterval(function(){
+ sock.send('echo-service', 'hey tobi');
+}, 500);
+```
+
+## Socket Options
+
+Every socket has associated options that can be configured via `get/set`.
+
+ - `identity` - The "name" of the socket that uniqued identifies it.
+ - `retry timeout` - The amount of time until retries will not be attempted again.
+
+PubSockets additionaly have options for batching:
+
+ - `batch max` - Max amount of messags to buffer in memory.
+ - `batch ttl` - Amount of time to buffer messages before sending.
+
## Binding / Connecting
- In addition to passing a portno, binding to INADDR_ANY by default, you
- may also specify the hostname via `.bind(port, host)`, another alternative
- is to specify the url much like zmq via `tcp://<hostname>:<portno>`, thus
- the following are equivalent:
+In addition to passing a portno, binding to INADDR_ANY by default, you
+may also specify the hostname via `.bind(port, host)`, another alternative
+is to specify the url much like zmq via `tcp://<hostname>:<portno>`, thus
+the following are equivalent:
```
sock.bind(3000)
@@ -140,11 +278,11 @@ sock.connect('tcp://0.0.0.0:3000')
## Protocol
- The wire protocol is simple and very much zeromq-like, where `<length>` is
- a BE 24 bit unsigned integer representing a maximum length of roughly ~16mb. The `<meta>`
- data byte is currently only used to store the codec, for example "json" is simply `1`,
- in turn JSON messages received on the client end will then be automatically decoded for
- you by selecting this same codec.
+The wire protocol is simple and very much zeromq-like, where `<length>` is
+a BE 24 bit unsigned integer representing a maximum length of roughly ~16mb. The `<meta>`
+data byte is currently only used to store the codec, for example "json" is simply `1`,
+in turn JSON messages received on the client end will then be automatically decoded for
+you by selecting this same codec.
```
octet: 0 1 2 3 <length>
@@ -153,31 +291,31 @@ sock.connect('tcp://0.0.0.0:3000')
+------+------+------+------+------------------...
```
- Thus 5 bytes is the smallest message axon supports at the moment. Later if
- necessary we can use the meta to indicate a small message and ditch octet 2 and 3
- allowing for 3 byte messages.
+Thus 5 bytes is the smallest message axon supports at the moment. Later if
+necessary we can use the meta to indicate a small message and ditch octet 2 and 3
+allowing for 3 byte messages.
## Codecs
- To define a codec simply invoke the `ss.codec.define()` method, for example
- here is the JSON codec:
+To define a codec simply invoke the `axon.codec.define()` method, for example
+here is the JSON codec:
```js
-var ss = require('axon');
+var axon = require('axon');
-ss.codec.define('json', {
+axon.codec.define('json', {
encode: JSON.stringify,
decode: JSON.parse
});
```
- __Note:__ codecs must be defined on both the sending and receiving ends, otherwise
- axon cannot properly decode the messages. You may of course ignore this
- feature all together and simply pass encoded data to `.send()`.
+__Note:__ codecs must be defined on both the sending and receiving ends, otherwise
+axon cannot properly decode the messages. You may of course ignore this
+feature all together and simply paaxon encoded data to `.send()`.
## Performance
- I haven't profiled or tuned anything yet but so far for on my macbook pro.
+I haven't profiled or tuned anything yet but so far for on my macbook pro.
64 byte messages:
@@ -231,20 +369,15 @@ $ make test
- more tests
- code cov
- acks
- - make socket options configurable
- - clean up queue / sock
- - emitter style on top of pubsub with multipart
- weighted fair queuing
- use mocha for tests
- - multipart frames
- cap batch size
- zero-copy for batches...
- make batching configurable... disable for lower latency
- - binary support for EmitterSocket (requires multipart)
- subscriptions
- ...
-## License
+## License
(The MIT License)
View
10 examples/dealer/dealer.js
@@ -0,0 +1,10 @@
+
+var axon = require('../..')
+ , sock = axon.socket('dealer');
+
+sock.set('identity', 'echo-service');
+sock.connect(3000);
+
+sock.on('message', function(msg){
+ sock.send(msg);
+});
View
13 examples/dealer/router.js
@@ -0,0 +1,13 @@
+
+var axon = require('../..')
+ , sock = axon.socket('router');
+
+sock.bind(3000);
+
+sock.on('message', function(from, msg){
+ console.log('%s said: %s', from.toString(), msg.toString());
+});
+
+setInterval(function(){
+ sock.send('echo-service', 'hey tobi');
+}, 500);
View
10 examples/reqrep/rep.js
@@ -0,0 +1,10 @@
+
+var axon = require('../..')
+ , sock = axon.socket('rep');
+
+sock.bind(3000);
+
+sock.on('message', function(msg, reply){
+ console.log('got: %s', msg.toString());
+ reply('pong');
+});
View
11 examples/reqrep/req.js
@@ -0,0 +1,11 @@
+
+var axon = require('../..')
+ , sock = axon.socket('req');
+
+sock.connect(3000);
+
+sock.on('message', function(msg){
+ console.log('got: %s', msg.toString());
+});
+
+sock.send('ping');
View
24 examples/router/rep.js
@@ -0,0 +1,24 @@
+
+var axon = require('../..');
+
+// foo service
+
+var foo = axon.socket('rep');
+
+foo.set('identity', 'foo');
+foo.connect(3000);
+
+foo.on('message', function(msg, reply){
+ reply('foo says: pong');
+});
+
+// bar service
+
+var bar = axon.socket('rep');
+
+bar.set('identity', 'bar');
+bar.connect(3000);
+
+bar.on('message', function(msg, reply){
+ reply('bar says: pong');
+});
View
14 examples/router/router.js
@@ -0,0 +1,14 @@
+
+var axon = require('../..')
+ , sock = axon.socket('router');
+
+sock.bind(3000);
+
+sock.on('message', function(from, delim, msg){
+ console.log(msg.toString());
+});
+
+setInterval(function(){
+ sock.send('foo', '\u0000', 'hello foo');
+ sock.send('bar', '\u0000', 'hello bar');
+}, 500);
Please sign in to comment.
Something went wrong with that request. Please try again.