distro
v0.4.0
Published
An small simple wrapper over UDP Datagrams to create clients/servers with an standard message format.
Downloads
69
Readme
"Distro" encapsulates the work needed to servers and clients for distributed systems.
UPDATES
0.4.0 Removed Redis into distro-redis as a plug-in 0.3.1 Added documentation for 0.3.0 0.3.0 Added support for Redis and major changes on the API. 0.0.5 Added support for TCP servers and clients 0.0.2 Initial release
The API of version 0.3.1 has significant changes when compared to the previous versions, please read below.
What's distro?
The distro module is intended to simplify the way services communicate with each other. It abstracts several different transports while providing a consistent interface. It also specifies a message format and comes with some helper factories to create and parse those messages.
It comes with some pre-packaged trasports for udp4, udp6 and tcp. You can also use redis (using pub-sub) via the distro-redis module plug-in. You can easily create your own transports as plug-ins as well (more details below). Note that there is not inter-operability between transports. Both clients and servers have to use the same transport to be able to talk to each other.
Usage cases.
Let's say you have an orders service that creates orders for customers. You also want to keep the rolling total for a given customer and you want the customer service to update the data on the customer.
Distro can easily dispatch a message to the proper service. On the orders service you will have some code like this:
var updateCustomer = distro.createMessage({uri: "/customer/", address: 'orders.services.com', port: 442200}; {})
distro.create('tcp').client({port: 41234, address: 'customer.service.com'}).send(updateCustomer);
Install
Simple do npm install distro
Creating a server
Creating a server is as simple as given the name of the transport to use and some server information needed for configuration.
var distro = require("distro");
var server = distro.create('udp4')
.server({port: 41234});
Supported transports at the moment are 'udp4', 'udp6' and 'tcp'.
You can register multiple handlers per server.
server.receive(handler1);
server.receive(handler2)
Servers can register handles for different verbs or for all the verbs.
server.receive(handleAllRequests);
server.post(uri, handlePost);
A server is nothing without a client
var distro = require("distro");
var client = distro.create('udp4')
.client({port: 41234});
The send method takes a distro Message
that you can easily create using the library.
var msg = distro.message({uri: "/identifier/"}, "Payload can be anything, even a string");
client.send(msg);
If you want to use the distro-redis plugin just add the distro-redis
module to your package.json
and create a new server or client passing the module as the argument of the create
method.
var distro = require("distro");
var distroRedis = require("distro-redis");
var client = distro.create(distroRedis)
.client({port: 41234});
var server = distro.create(distroRedis)
.server({port: 41234});
The Messages
Messages need at least two parameteres, a headers object and a payload. The headers needs at least one property (uri).
var header = {uri: "/object/main" };
var msg = distro.message(headers, payload);
If you want to receive confirmation once the message is received you can add the information for the server that will receive the confirmation to the headers object. (This structure will change in the next version)
var header = {
uri: "/object/main",
address: "localhost",
port: 42234
};
var msg = distro.message(headers, payload);
The server(s) that receives a message with origin information will send back a RECEIVED message to such origin. (This will change as well in the next version) The payload of a RECEIVED message is the id of the message.
Messages Id are autogenerated UUID, the payload of a message can be any JSON serializable object. This is a very important consideration since recursive objects will not work properly at the moment.
Working with "verbs"
The headers object can have a verb
property that maps to some of the http verbs. At the moment the supported verbs are HEAD, GET, POST, PUT, DELETE
and PATCH
.
What do I mean with supported verbs, you may ask?
The server object can register different handlers for each of those verbs. Instead of registering handlers with the receive
method you can use specific verbs methods.
var server = distro.create('tcp')
.server({port: 41234})
server.head(uri, handleHeadVerb);
server.get(uri, handleGetVerb);
server.post(uri, handlePostVerb);
server.put(uri, handlePutVerb);
server.del(uri, handleDeleteVerb);
server.patch(uri, handlePathVerb);
You don't need to specify the get
verb for messages. If you registered handlers with the get
method and your messages don't have a verb, this handler(s) will be used.
You can still add handlers to receive
that will be called no matter the verb (or the uri) of the messages, this can be helpful for audit, logging or error handlers purposes.
API Documentation
parse(data)
Given a serialized Message
returns a Message
object
message(headers, payload)
Creates a new Message
object with the given headers and payload.
create(transport, [logger])
transport
can be a string identifying the bundled transport or a transport object.
The logger
is any object that implements the log
method. If a logger is not given the native console
object will be used.
Returns a distro
object
distro.server(serverInfo)
The serverInfo
object contains the port
and address
for the underlying transport. If adrress
is not provided the default is localhost
or 127.0.0.1
Returns a Server
object.
distro.client(serverInfo)
The serverInfo
object contains the port
and address
for the underlying transport. If adrress
is not provided the default is localhost
or 127.0.0.1
Returns a Client
object.
server.receive(callback)
Adds a listener that will be called each time the server is called, without consideration of the verb or uri used in the message
headers
server.head(uri, callback)
server.get(uri, callback)
server.post(uri, callback)
server.put(uri, callback)
server.del(uri, callback)
server.patch(uri, callback)
Adds the listener to be called when a message is received for the given verb and uri specified on the message
headers
server.close()
Stops and close the server.
client.send(message)
The message
have to be a Message
object.
new Message(id, headers, payload)
The id
is expected to be a UUID.
The headers
object contains a uri
, an address
for the server/client to talk to and a port
number.
The payload
should be a 'flat' serializable object.
You will usually create new messages
using the .message()
method of the library directly.
message.toString()
Returns a string representation of a serialized Message
message.toBuffer()
Return a buffer with the result of calling toString()
on the Message