Friday, April 9, 2010

Including Changed Document in CouchDB (with a node.js detour)

‹prev | My Chain | next›

It occurs to me that, before moving on from node.couch.js, I ought to use it to explore some of the CouchDB changes API parameters.

First up, I was excited to see in the CouchDB documentation that version 0.11 can include the entire document in the change notification. To get documents included, I need to pass include_docs=true in the request for the changes API. In node.couch.js, this goes in the start() method:
  var start = function () {
var request = c.h.request("GET", c.url.pathname+'?'+querystring.stringify(options)+'&heartbeat=600000&include_docs=true', {'accept':'application/json'});
request.addListener('response', function(response) {response.addListener('data', changesHandler);});
request.close();
};
Running node.couch.js now produces:
cstrom@whitefall:~/repos/node.couch.js$ node ./changes/lib/service.js http://localhost:5984
{"seq":83,"id":"test","changes":[{"rev":"1-4c6114c65e295552ab1019e2b046b10e"}]}
Hey! There's no complete document in there!

Oops. I forgot that localhost is still running version 0.10. Fortunately, I have a bunch of 0.11 VMs, so I couch-replicate localhost with one of them:
cstrom@whitefall:~/repos/node.couch.js$ couch-replicate seed localhost couch-011a.local
Linking replication hosts...
Then, running node.couch.js against the 0.11 database and making a change:
cstrom@whitefall:~/repos/node.couch.js$ node ./changes/lib/service.js http://couch-011a.local:5984
{"seq":84,"id":"test","changes":[{"rev":"2-cfcd6781f13994bde69a1c3320bfdadb"}]}
Damn. That looks an awful lot like a 0.10 change document. What is going on here?

After a goodly long time, I finally notice that there are no changes requests in the 0.11 logs:
[Fri, 09 Apr 2010 21:58:13 GMT] [info] [<0.4240.0>] 192.168.56.1 - - 'GET' /_all_dbs 200

[Fri, 09 Apr 2010 21:58:13 GMT] [info] [<0.4276.0>] 192.168.56.1 - - 'GET' /seed/_all_docs?startkey=%22_design%2F%22&endkey=%22_design0%22 200

[Fri, 09 Apr 2010 21:58:13 GMT] [info] [<0.4277.0>] 192.168.56.1 - - 'GET' /test/_all_docs?startkey=%22_design%2F%22&endkey=%22_design0%22 200

[Fri, 09 Apr 2010 21:58:13 GMT] [info] [<0.4280.0>] 192.168.56.1 - - 'GET' /seed/_design/test 200

[Fri, 09 Apr 2010 21:58:13 GMT] [info] [<0.4278.0>] 192.168.56.1 - - 'GET' /seed/_design/meals 200

[Fri, 09 Apr 2010 21:58:13 GMT] [info] [<0.4281.0>] 192.168.56.1 - - 'GET' /test/_design/meals 200

[Fri, 09 Apr 2010 21:58:13 GMT] [info] [<0.4279.0>] 192.168.56.1 - - 'GET' /seed/_design/recipes 200

[Fri, 09 Apr 2010 21:58:13 GMT] [info] [<0.4282.0>] 192.168.56.1 - - 'GET' /test/_design/recipes 200

[Fri, 09 Apr 2010 21:59:13 GMT] [info] [<0.4283.0>] 192.168.56.1 - - 'GET' /_all_dbs 200
That was definitely working on the localhost/v0.10 server. In fact....

Those requests are still going there:
[Sat, 10 Apr 2010 01:58:16 GMT] [debug] [<0.386.0>] 'GET' /seed/_changes?feed=continuous&since=84&heartbeat=600000 {1,1}
Headers: [{'Accept',"application/json"},{'Connection',"close"}]

[Sat, 10 Apr 2010 01:58:16 GMT] [debug] [<0.387.0>] 'GET' /test/_changes?feed=continuous&since=138&heartbeat=600000 {1,1}
Headers: [{'Accept',"application/json"},{'Connection',"close"}]
How are earth are some of the node.couch.js requests hitting the couch-011a server but others going against the localhost server? Turns out this can traced back to the Listener initialization:
//...
this.url = url.parse(uri);
this.options = options;
this.h = http.createClient(this.url.port, url.host);
//...
url.host is undefined in this context—it ought to be this.url.host, which is defined by the url.parse() statement. So I change this to read:
//...
this.url = url.parse(uri);
this.options = options;
this.h = http.createClient(this.url.port, url.host);
//...
Then I rerun the script only to find... no changes!

Grr... After reading the node.js documentation even more, I find that url.hostname is what I really want (it returns "couch-011.local", whereas url.host returns "couch-011a.local:5984"). So I make the call with hostname:
//...
this.url = url.parse(uri);
this.options = options;
this.h = http.createClient(this.url.port, url.hostname);
//...
With that, I finally get the change to go through. Not only does the change come back, but I also see the document included:
cstrom@whitefall:~/repos/node.couch.js$ node ./changes/lib/service.js http://couch-011a.local:5984
{"seq":23,"id":"test","changes":[{"rev":"4-b3489c0d8df6c07ff3274ac84c310682"}],"doc":{"_id":"test","_rev":"4-b3489c0d8df6c07ff3274ac84c310682","foo":"baz"}}
OK, that was a little harder than I had hoped, but I am glad to have had the chance to play about with node.js a bit more. It was also nice to see include_docs in action. Tomorrow, I still want to play with the timeout and heartbeat parameters to the CouchDB changes API. Once I have an understanding of those, I will move onto to other node.js libraries.

(commit of the hostname fix to my forked copy of node.couch.js)


Day #68

No comments:

Post a Comment