eventerface
Evented API development framework for distributed, loosely coupled architectures.
Why Eventerface?
A different way of thinking about events
Node.js event-driven model is awesome, but there is something weird about it: event emitters need to be known by the parties interested in generating events for them. This is not a problem in cases where the parties know and have access to each other, like a conversation between friends:
var EventEmitter = EventEmitterfriend1 =friend2 = ;// friend1 says 'hi!' to friend2friend2;// friend2 listens to the 'say' event and answers back to friend1friend2;// friend1 listens to the 'say' event and continues the conversationfriend1;
However, not all events and interactions in the real world happen between parties that know each other or each other's names (or variables), so a different approach is needed in order to enable decoupled interactions such as conversations between strangers, which are possible in the real world because there is a namespace that carries voice events between them: the air.
Dealing with events, not event emitters
Using Eventerface, the previous conversation can be written in such a way that it doesn't matter if the parties know each other or not, because the events are emitted into a namespace (e.g. the air) using the namespace's event emitter, not the other parties' emitters:
var eventerface =air = eventerface // A namespace that carries events between the member partiesperson1 =person2 = ;// person1 says 'hi!' to person2person1; // Notice that person1 uses its own emitter instead of person2's// person2 listens to the 'say' event, and answers back to person1person2;// person1 listens to the 'say' event and continues the conversationperson1;
In this way, when a party wants to emit an event it only needs to emit it into a given namespace, and it will be automatically routed to all the listeners subscribed to that event in the same namespace (e.g. people in the same room). Notice that thinking about events, and not about event emitters, causes a change in notation that makes more sense when reading the code, because when a person wants to say something, she uses her own mouth (i.e. calls her own #emit method), not the target person's mouth.
Usage
Local (same file)
// Create the 'app' local namespacevar app =emitter =listener = ;listener;emitter;
Global (different files, same file system)
Eventerface enables the creation of event namespaces that are accessible from more than one file in the same file system by using a unix socket server to create a global namespace.
First, the global namespace has to be created in the designated main file using the #create method:
// main.jsvar eventerface = ;// Create the 'app' global namespaceeventerface;
Then, any other files in the application folder can get access to the created global namespace using the #find method:
// database.jsvar eventerface = ;// Find the 'app' global namespaceeventerface;
In this usage example, the main.js module listens to the 'ready' event of the database module and then emits a 'query' event to the database. Notice that the modules know nothing about the origin of the events nor the location of the other modules, because Eventerface emitters only care about event names and interact directly with the namespace as a whole, not with particular event emitters.
Distributed (different file systems)
Eventerface can also be used to create evented interfaces that are accessible from different servers or file systems in order to establish one-to-one, one-to-many and many-to-one event-based communications.
- Distributed Channels
Distributed channels are point-to-point interfaces that allow two remote parties to send and receive events from each other without worrying about the underlying TCP connection.
In order to create a distributed channel, a string containing the 'channel://' prefix followed by the desired port number of the channel must be passed as a parameter to the #create method:
// database.js on databaseHost servervar eventerface = ;// Create a distributed channel on port 'databasePort'eventerface;
Then, a file on another server can connect to this channel using the #find method with a string containing the 'channel://' prefix followed by the target host and port number separated by a colon:
// app.js on appHost servervar eventerface = ;// Find a distributed channel on host 'databaseHost' and port 'databasePort'eventerface;
In this usage example, the database.js file on host 'databaseHost' creates a distributed channel on port 'databasePort', subscribes to the 'query' event and emits a 'result' event after querying the database. On another server ('appHost'), the app.js file connects to the database's channel on host 'databaseHost' and port 'databasePort', emits the 'query' event and subscribes to the 'result' event for further handling.
- Distributed Stations
Eventful APIs
Eventerface can also be used to expose collections of event related resources through RESTlike Web APIs.
Examples
License
MIT