adobe/brackets — pull request #6193 by iwehrman (2013-12-06 01:53:09+00:00)
Title: NodeDomain

This pull request has three parts:

1. A new `NodeDomain` module, which is a high-level wrapper around `NodeConnection`. This makes it easy to open a connection and load a single domain, and then execute the domain's commands and listen for its events. The wrapper handles, in particular, connection and domain loading and reloading.
The inline documentation gives the following usage example:
```
var myDomain = new NodeDomain("someDomain", "/path/to/SomeDomainDef");
$result = myDomain.exec("someCommand", arg1, arg2);

$result.done(function (value) {
// the command succeeded!
});

$result.fail(function (err) {
// the command failed; act accordingly!
});

$(myDomain).on("someEvent", someHandler);
```
2. A refactoring of `StaticServer` to use `NodeDomain` instead of manipulating `NodeConnection` directly. The previous code had been copied and pasted regularly, but had a few shortcomings, including redundant timeouts (`NodeConnection` handles this already), failure to handle disconnected sockets, and, in some cases, a silent fail-fast behavior on command execution where simply waiting would suffice. (If the `NodeConnection` isn't connected, don't abort; just wait for it to come back up!)
3. Finally, it also fixes a race condition in `StaticServerDomain` that was causing the `LiveDevelopment` unit tests to fail unpredictably.
The problem is as follows: when `StaticServerDomain` receives an HTTP request for a filtered path, it emits a `filterRequest` event to Brackets to have the file contents at that path manipulated before sending the response. Brackets later calls the `writeFilteredResponse` command with the manipulated data, which triggers the HTTP response. `StaticServerDomain` connects these filtered responses to their original filter requests by way of a map of callbacks keyed on the requested paths. But, as a consequence, when the `StaticServerDomain` HTTP server receives *two* concurrent requests for the same path, it only stores *one* response callback. The second filtered response is then be dropped, no longer having any response callback at the given path, and the second request---whose response callback has been overwritten---will always time out. The problem is solved here by adding a unique identifier to each `filterRequest` and keying callbacks on this identifier.