Friday, September 24, 2010

Down and node-dirty

‹prev | My Chain | next›

Having exhausted (for the moment) my exploration of the upcoming fab.js version 0.5, I feel ready to move onto the next big thing in my (fab) game. First, I merge my topic branch back into master and push everything to the github repository. With that, I am ready to get dirty:
cstrom@whitefall:~/repos/my_fab_game$ git co -b dirty
Switched to a new branch 'dirty'
Yup. In this branch, I am going to replace my beloved CouchDB with Felix Geisendörfer's node-dirty as the player store.

First up, I install it via npm:
npm install dirty
npm info it worked if it ends with ok
npm info version 0.1.27-12
npm info fetch http://registry.npmjs.org/dirty/-/dirty@0.9.0.tgz
npm info fetch http://registry.npmjs.org/gently/-/gently-0.8.0.tgz
npm info install dirty@0.9.0
npm info install gently@0.8.0
npm info activate dirty@0.9.0
npm info activate gently@0.8.0
npm info build Success: dirty@0.9.0
npm info build Success: gently@0.8.0
npm ok
It ends with "ok" so it worked :)

Next, I work through the player store object replacing node-couchdb calls with node-dirty calls. The player get() method used to be a wrapper around the node-couchdb getDoc() method:
   get: function(id, callback) {
Logger.debug("[players.get] trying to get: " + id);
db.getDoc(id, function(err, res) {
if (err) {
Logger.warn(JSON.stringify(err));
}
callback(res);
});
}
Now it can send the results of a node-dirty get() directly to the supplied callback:
   get: function(id, callback) {
Logger.debug("[players.get] trying to get: " + id);
callback(db.get(id));
}
Really, there is no need for the get() method to be async (callback-based) anymore. It could just as easily block for the node-dirty get(). I leave it as-is to minimize API changes—at least for now.

In addition to getting players, I need to update the saving of them as well. The node-couchdb saveDoc():
        db.saveDoc(player);
...becomes a node-dirty set():
        db.set(status.id, player);
In the node-couchdb version, I could rely on the id attribute in the document to store the proper ID in CouchDB. In node-dirty, I need to be explicit.

Lastly, I need to be able to drop players. In the node-couchdb version, I had to get the player before it could be removed (to satisfy optimistic locking):
  drop_player: function(id) {
Logger.info("players.drop_player " + id);
this.faye.publish("/players/drop", id);

this.get(id, function(player) {
Logger.debug("[players.drop_player] " + inspect(player));
if (player) db.removeDoc(id, player._rev);
});
}
There is no need for that in node-dirty. To be precise, there is no support for locking in node-dirty, which could certainly prove an issue at some point. For now, I will put that concern aside and remove players with a simple rm() call:
  drop_player: function(id) {
Logger.info("players.drop_player " + id);
this.faye.publish("/players/drop", id);
db.rm(id);
}
With that, I am ready to fire up my game. Sadly, I find:
Caught uncaughtException: Error: Cannot find module 'constants'
at loadModule (node.js:275:15)
at require (node.js:411:14)
at Object.<anonymous> (/home/cstrom/.node_libraries/.npm/dirty/0.9.0/package/lib/dirty/dirty.js:6:17)
at Module._compile (node.js:462:23)
at Module._loadScriptSync (node.js:469:10)
at Module.loadSync (node.js:338:12)
at loadModule (node.js:283:14)
at require (node.js:411:14)
at Object.<anonymous> (/home/cstrom/.node_libraries/.npm/dirty/0.9.0/package/lib/dirty/index.js:1:80)
at Module._compile (node.js:462:23)
My uncaught exception handler catches another one:
// Don't crash on errors
process.on('uncaughtException', function (err) {
console.log('Caught uncaughtException: ' + err.stack);
});
It prevents the crash, but the question remains: how do I prevent the exception in the first place. If node cannot find the 'constants' module, perhaps I can install it from npm?
cstrom@whitefall:~/repos/my_fab_game$ npm install constants
npm info it worked if it ends with ok
npm info version 0.1.27-12
npm ERR! ! 404 !
npm ERR! ! 404 ! It seems like 'constants' is not in the registry
npm ERR! ! 404 ! You should bug the author to publish it.
npm ERR! ! 404 !
npm ERR! Error: 404 Not Found: constants
...
npm not ok
Guess not.

I recently discovered that yes, you can read the node.js source code, so that is what I do. And I find that ENOENT can be accessed from process.binding('net'):
node> process.binding('net').ENOENT
2
After replacing the constants.ENOENT references with process.binding('net').ENOENT, everything works! So I do the right thing and submit a pull request for the real node-dirty.

That one minor (and easily resolved) issue aside, the move to node-dirty was pure win. I no longer require a separate CouchDB server to run my (fab) game, and it seems as though it will be more than sufficient to meet my needs—the game will crap out long before 1 million players start to impact node-dirty.

I am still a bit concerned about record locking, but I will leave that question for another day.

Day #236

No comments:

Post a Comment