Saturday, September 4, 2010

Faye with Fab (v0.5)

‹prev | My Chain | next›

After looking through the new v0.5 brannch of fab.js last night, I'd like to see if I can get it working with my (fab) game tonight.

I am building branches upon branches in my (fab) game's repository as I explore different things. Most recently, I have been working on an express branch which was a branch of a faye branch. To experiment with fabjs, I need to switch back to the faye/fabjs branch. I cherry pick some of the node-couchdb / CouchDB work that blossomed after I started on the express branch. I do not know if I will end up using fab or express, but I definitely want CouchDB.

Anyhow, I cherry pick everything, fix a few things that leaked though, and am ready to try things out:
cstrom@whitefall:~/repos/my_fab_game$ ./game.js 
[INFO] Starting up...

/home/cstrom/repos/my_fab_game/game.js:75
( fab )
^
ReferenceError: listen_with_faye is not defined
at Object.<anonymous> (/home/cstrom/repos/my_fab_game/game.js:75:1)
at Module._compile (node.js:461:23)
at Module._loadScriptSync (node.js:468:10)
at Module.loadSync (node.js:338:12)
at Object.runMain (node.js:521:24)
at node.js:751:10
OK. That was to be expected. The listen_with_faye (fab) app was part of my fork only. I cannot cherry pick that in my fork because the code structure changed so radically in fabjs between v0.4 and v0.5, but I can copy the code directly into the main index.js file of v0.5 fabjs.

Or I could if the fab.listen app had not changed so much. The latest version looks something like this:
fab.listen = function( write, port ) {
var url = require( "url" );

return fab.stream( function read( stream ) {
require( "http" )
.createServer( listener( stream ) )
.listen( port );

return stream( write );
});

function listener( stream ) {
// ...
}

}
The main problem here is not the switch to streams (though that does make a direct patch from my existing listen_with_faye impossible). No, the main problem is going to be that listener. It is big. Since it is hidden inside fab.listen, I cannot get access to it from elsewhere.

I can either cargo-code the entire app to a new version of listen_with_faye or tweak the v0.5 fab.listen directly. I ain't cargo coding, so I opt for the latter.

I could add a faye client directly in the fab.listen function. I am just playing at this point, so that would not be out-of-the-question. Still, it would be better to keep things as close to upstream as possible, especially with so many changes anticipated.

So I opt to supply an additional callback argument to be used to attach things to the server:
fab.listen = function( write, port, fn ) {
var url = require( "url" );

return fab.stream( function read( stream ) {
var server = require( "http" )
.createServer( listener( stream ) );

if (fn) fn(server);

server.listen( port );

return stream( write );
});

function listener( stream ) {
//....
}
}
One of the problems with callback code is, to what does the callback apply? Here, I want it to apply to the server that I am establishing so that I can attach a faye listener. I might just as well want to attach it to something in the listener function inside fab.listen. More likely, I might pass in a callback for the server.listen so that I could establish my server-side faye clients once the sockets are in place. Would the third argument end up being an object literal (hash) of possible callbacks? If so, testing become a big pain. Ick.

For now, I am none too concerned. I just want to get it working. But if I end up sticking with fab, I'll need something like that and will have to convince Jed it is worth the hassle. Problems for another day. For now, let's see if that works.

Back in my (fab) game, I create the faye listener (which had been in my old fab.listen_with_faye) and attach it via the callback:
function attach_faye(server) {
var faye_server = new faye.NodeAdapter({
mount: '/faye',
timeout: 45
});

faye_server.attach(server);

// attach the extension ensuring player messages come from the same
// client that originally added player to the room
faye_server.addExtension(serverAuth);
}

with ( require( "fab" ) )

( fab )

// Listen on the FAB port and establish the faye server
( listen, 0xFAB, attach_faye )

// Lots and lots of (fab) code commented out here because it no longer
// works with v0.5

()
I start up my server and switch over to node-repl. If the faye listener was attached to the server, then I ought to be able to attach a client, subscribe to a channel, and then publish a message to it:
cstrom@whitefall:~/repos/my_fab_game$ node-repl
Type '.help' for options.
(The REPL can also be started by typing 'node' without arguments)
node> var faye = require("faye");
node> var client = new faye.Client("http://localhost:4011/faye");
node> var sub = client.subscribe("/foo", function(message) { console.log(message) });
node> client.publish("/foo", "test 123");
node> test 123
Nice! When I publish a message to the "/foo" faye channel, the subscription receives the message and console.logs it as expected.

Most of the commented out, v0.4 (fab) code was static file serving. I seem to recall that a static file server has already been written for v0.5, so I may investigate that tomorrow. Or, if I'm feeling crazy, I may explore some of those HTML fab apps instead...


Day #216

No comments:

Post a Comment