Make your burro a bit more comfortable with RPC!
Pillion is an RPC system that sits on top of object streams. It's designed to be the potatoes to burro's meat, but will actually work with any stream that allows you to send/receive arbitrary objects.
Everything is based around callbacks; you can pass a function in basically anywhere. There are some tricky bits around managing lifecycles right now, but that'll likely change in the future.
If you just want to get your hands dirty, here's how I'd suggest doing it. There's more detailed documentation down below, if you want it. This example uses burro and will only work in node 0.10.0 or above.
// server.js
var net = require("net"),
burro = require("burro"),
pillion = require("pillion");
var server = net.createServer(function(_socket) {
var socket = burro.wrap(_socket),
rpc = new pillion(socket);
rpc.provide("greet", function(name, cb) {
cb("hi there, " + name);
});
});
server.listen(3000);
// client.js
var net = require("net"),
burro = require("burro"),
pillion = require("pillion");
var _socket = net.connect(3000),
socket = burro.wrap(_socket),
rpc = new pillion(socket);
rpc.callRemote("greet", "friend", function(res) {
console.log(res); // prints "hi there, friend"
});
Available via npm:
$ npm install pillion
Or via git:
$ git clone git://github.com/deoxxa/pillion.git node_modules/pillion
constructor
Constructs a new Pillion object, optionally piping to/from a supplied Duplex stream and/or adding some methods.
new Pillion([duplexStream], [methods]);
// basic instantiation
var p = new Pillion();
// instantiation with a stream
var p = new Pillion(something.createDuplexStream());
// instantiation with method map
var p = new Pillion({
hi: function(name, cb) { cb("hi there, " + name); },
bye: function(name, cb) { cb("see you later, " + name); },
});
// instantiation with both
var p = new Pillion(something.createDuplexStream(), {
hi: function(name, cb) { cb("hi there, " + name); },
bye: function(name, cb) { cb("see you later, " + name); },
});
Arguments
- duplexStream - an object implementing the streams2 "duplex stream" API. It
must have the following functions defined:
read
,write
,pipe
,unpipe
. - methods - a hash of name -> method pairs.
provide
Adds a method to the pillion object, making it available for remote peers to call.
pillion.provide(name, function);
pillion.provide("hi", function(name, cb) {
cb("hi there, " + name);
});
Arguments
- name - a string used to identify the method.
- function - a function that implements the method.
callRemote
Executes a remote method with semantics similar to Function.call
.
pillion.callRemote(name, [arg1, [arg2, ...]]);
pillion.callRemote("hi", "honey bear", function(response) {
// outputs "hi there, honey bear"
console.log(response);
});
Arguments
- name - name of the remote method.
- argN - arguments for the remote method.
applyRemote
Executes a remote method with semantics similar to Function.apply
.
pillion.applyRemote(name, [args]);
pillion.applyRemote("hi", ["honey bear", function(response) {
// outputs "hi there, honey bear"
console.log(response);
}]);
Arguments
- name - name of the remote method.
- args - an array of arguments for the remote method.
bindRemote
Returns a callable, portable reference to a remote method with semantics similar
to Function.bind
.
pillion.bindRemote(name, [arg1, [arg2, ...]]);
var fn = pillion.bindRemote("hi");
fn("honey bear", function(response) {
// outputs "hi there, honey bear"
console.log(response);
}]);
Arguments
- name - name of the remote method.
- args - an array of arguments for the remote method.
#methodAdded
methodAdded
is an event that's fired with the name of a method that has been
recently added to the remote peer.
pillion.on("methodAdded", function(name) { ... });
local.on("methodAdded", function(name) {
console.log(name);
});
Parameters
- name - name of the remote method.
#methodRemoved
methodRemoved
is an event that's fired with the name of a method that has been
recently removed from the remote peer.
Note that there is currently no public API for removing methods from a Pillion object, so this will probably never be fired right now.
pillion.on("methodRemoved", function(name) { ... });
local.on("methodRemoved", function(name) {
console.log(name);
});
Parameters
- name - name of the remote method.
Also see example.js.
var stream = require("stream"),
Pillion = require("pillion");
// Set up the first peer, bob, which will be acting kind of like a "server"
var bobStream = new stream.Duplex({objectMode: true});
bobStream._read = function _read(n, respond) {};
bobStream._write = function _write(input, done) {
aliceStream.push(input);
done();
};
var bob = new Pillion(bobStream);
// Provide a "reverse" method that can be called by remote peers. It takes a
// string and a... callback?! You bet your ass it takes a callback! When we call
// that callback, it actually signals the other side (alice) to call whatever
// function is associated with it... Wild stuff.
bob.provide("reverse", function reverse(str, cb) {
console.log("calling reverse with argument: " + str);
// Okay, let's tell alice the result of our secret word-reversing algorithm.
// We'll call her callback with the result and another callback that we want
// her to call when she gets the response.
cb(str.split("").reverse().join(""), function onThanks(thx) {
console.log("got thanks: " + thx);
});
});
// Set up the second peer, alice, which will be taking a kind of "client" role
var aliceStream = new stream.Duplex({objectMode: true});
aliceStream._read = function _read(n, respond) {};
aliceStream._write = function _write(input, done) {
bobStream.push(input);
done();
};
var alice = new Pillion(aliceStream);
// Call the "reverse" method on bob. Give the arguments "hello" and... a
// callback! That's right, the remote side is going to call this callback on our
// side when it feels like it. Funky. Our callback gets the reversed string and
// ...ANOTHER CALLBACK?! WHAT THE HECK?! That's right, we're calling *another*
// callback on bob. CRAZY.
alice.callRemote("reverse", "hello", function onReverse(str, kthx) {
console.log("got response from reverse, result is: " + str);
kthx("bye");
});
Output:
calling reverse with argument: hello
got response from reverse, result is: olleh
got thanks: bye
3-clause BSD. A copy is included with the source.
- GitHub (deoxxa)
- Twitter (@deoxxa)
- ADN (@deoxxa)
- Email (deoxxa@fknsrs.biz)