Tuesday, February 14, 2012

Event Hub

Event Hub

Get caught up:
Part 1: http://randomgoo.blogspot.com/2012/02/release-event-hub-web-30-introduction.html
Part 2: http://randomgoo.blogspot.com/2012/02/events.html
Part 3: http://randomgoo.blogspot.com/2012/02/event-listeners-get-up-to-speed-first.html

Quick recap - Web 3.0 is two-way asynchronous programming - events on the way out and another event or a callback on the way back.

The hub (maybe more like a switch) is pretty dumb with some minimal smarts.

The Dumb

The hub listens on a port for connections from interested modules.  Once connected the hub relays events to all connected modules (yes even back to the module that fired the event - the handler may be there too!).  Nice and dumb.

The Smart

Cry not for our poor hub.  It also has some basic smarts.  The smarts are necessary for 2 separate reasons:

1. sessions
2. trust


Each connection to the hub is associated with a session, not an entire session, just a unique identifier.  This identifier, hmmm... identifies a session uniquely.  Didn't I just say that?  Anyway the hub itself does not use the session key, but merely passes it along to 'trusted' modules.  'Trusted' modules can use this identifier to store data associated with this session if they so choose. 
The hub injects the session key into any event arguments before passing the event on to any 'trusted' connected modules.


Some connected modules are more special than others.  These are typically server-side listeners that do actual work, like updating a database or flipping switches in a nuclear reactor.  Not all modules are created equally.  We wouldn't want just anyone connecting to our hub and responding to the 'reactor:TurnOn' event now would we?  
So a module is 'trusted' by the hub if, upon connection, it provides a secret key shared only by trusted modules and the event hub.  
So what does a 'trusted' module get that a plain old untrusted one doesn't?
It gets 2 things, the session key and responder status.
The session key is mentioned above, it's just a unique key that identifies the event emitter.
'Responder status' means a trusted module gets to listen for certain events, and ONLY that ONE trusted module will be delivered that event.
FOR INSTANCE the 'user:add' event.
Without a trusted listener for that event the 'user:add' event will be broadcast to all modules.  So a 'bad guy' can connect to your event hub and listen for that event and when a good guy tries to create a user (including username and password in the event data) the bad guy will get it.
Even without a bad guy some events only want one listener.  What if I had three modules, trusted ones event, listening for the 'user:add' event?  They would all get the event, the first one would succeed (say by adding the user to the database) while the other 2 would fail, as the user now already exists.  Even worse what about events with callbacks?  The first callback would work and the next 2 callbacks would fail as the callback already happened.

SO events with callbacks can only have ONE listener.  Events that change stuff should only have ONE listener.  That ONE listener should be 'trusted'.

SO the event hub must support trusted modules AND the ability to have only ONE listener for an event.  And as an extra added bonus IF the module is trusted it gets the session key to boot.

Ok stay with me here just about done!  Here's how it all comes together:

Module <-> Event Hub Initialization

Clients, typically browsers or command line clients, connect to the event hub with no special privileges.  They can emit all the events they want, not knowing or caring about all of this 'trust' or 'session' stuff.
Server-side modules can connect to the event hub with a shared key giving them 'trusted' status.  These trusted modules can request to listen for events which they deem 'unicast' using event-listening syntax sugar.

Unicast Event to Trusted Listener

Ok everyone is connected to the hub now, now the user creates a new user and the client fires the 'user:add' event with the username and password.  This unbeknownst-to-the-client is a unicast event that ONLY gets sent to the one trusted server-side module that is listening for it.  This handler adds the user to the database and can either fire another event upon successful completion or use a callback to respond with the operation's status.

Event with Session Key

Great so we have created a new user, now that user wants to log in.  User fills in their username and password and a 'user:login' event is emitted.  The trusted unicast listener (doesn't have to be unicast in this case) gets the username & password & session key from the event hub and verifies the credentials against the database.  A match!  Now the listener would use the unique session key to create a session object in the database with the username of the authenticated user and again uses the callback or emits a 'user:loggedIn' event of its own to report status.

Great, now that user wants to change their password.  So the client fires a 'user:changePassword' (or 'user:updateUser' or whatever) event with the username, new password and the event hub adds in the session key before handing re-firing the event to the trusted listener (perhaps unicast).  The listener verifies the username in the event matches the username associate with the session key and if they match updates the password.  Finally it can either fire an event 'user:passwordUpdated' (or whatever) or use a callback to report back status.

Doesn't that all just make perfect sense??

So our event hub has sessions and trusted modules and unicast, everything else is just dumb event and callback passthru.


An event hub can operate just fine over SSL.  You will not get the pretty 'lock' or 'green' URL bar but all of your data can very easily be sent encrypted.

Coming up next: languages, implementations, and deployment - stay tuned!!

No comments:

Post a Comment