Friday, June 18, 2010

Error Handling in Fab.js

‹prev | My Chain | next›

In the course of last night's work, I inadvertently crashed the fab.js backend with the following backtrace:
broadcasting to 3 players: <script type="text/javascript">window.parent.player_list.bounce_player({"id":"bo)</script>

undefined:1

^
SyntaxError: Unexpected token ILLEGAL
at Object.parse (native)
at listener (/home/cstrom/repos/my_fab_game/game.js:50:39)
at IncomingMessage.<anonymous> (/home/cstrom/.node_libraries/fab/apps/fab.nodejs.js:29:36)
at IncomingMessage.emit (events:25:26)
at HTTPParser.onBody (http:98:23)
at Stream.ondata (http:745:22)
at IOWatcher.callback (net:373:31)
at node.js:204:9
I am unsure of the cause of the clipped JSON string ("{"id":"bo"), but it hardly matters. This could happen due to bug, network failure or someone hacking around. Regardless of the cause, I need to handle it better than crashing the backend.

To prevent crash, I make use of a technique that I have rarely, if ever, used in Javscript: try-catch exception handling. The JSON parser is throwing me a perfectly catch-able exception here, so let's see if I can catch it:
  ( /bounce/ )
( function() {
var out = this;
return function listener( obj ) {
if ( !obj ) out();
else if ( obj.body ) {
try {
broadcast(comet_bounce_player(obj.body));
update_player_status(JSON.parse(""+obj.body));
} catch (e) {
puts("[bounce_handler] error type: " + e.type +
", message: " + e.message);
}
finally {
out();
}
}
return listener;
};
} )
If I have done this correctly, sending invalid JSON should result in an error message being printed out, but no crash. For good measure, I add a finally block to the try-catch chain so that I tell the downstream browser that I have nothing left to say (true regardless of success).

So I fire up the game a send bogus JSON:
cstrom@whitefall:~/repos/my_fab_game$ curl http://localhost:4011/bounce -d '{id:"foo'
Switching over to the backend, I see:
broadcasting to 3 players: 

[bounce_handler] error type:unexpected_token, message: Unexpected token ILLEGAL
Nice! I get the error message output for which I hoped, but... I still seem to be broadcasting the bogus JSON to all connected players. Checking the Javascript console of one of the 3 attached players, I see that I am, indeed, sending that bogus JSON:



Happily, that is easy enough to prevent: just fail early by putting the JSON parse first in the try block:
//...
try {
update_player_status(JSON.parse(""+obj.body));
broadcast(comet_bounce_player(obj.body));
} catch (e) {
//...
With that, I have a much more robust client and server—all thanks to a simple try-catch. Up tomorrow: more fab.js error handling as I try to generalize this to other upstream apps that are handling game actions.

Day #138

No comments:

Post a Comment