Update notifications sent by a database allow me to react to changes submitted to it in almost real-time without having to continuously (or periodically) poll said database. Note, that update notifications are not the same thing as database triggers as known in the relational database world: update notifications are submitted after a database modification has occurred -- there is no way to avoid the update. These notifications are typically consumed by an external process which then somehow reacts to the update. CouchDB has support for two types of update notifications (of which I'm aware):

Update notifications powered by an external process, and

Change notifications using the changes API.

External process

CouchDB uses external processes which read an update notification on stdin whenever a database is modified. To configure one or more such processes, edit your CouchDB's local.ini to read

[update_notification]
jpnoti=/usr/bin/couchjp

This process receives a JSON string as a notification which includes the name of the database that was just modified.

For example, whenever my twitter database changes, the couchjp program receives the following line on stdin:

{"type":"updated","db":"twitter"}

Your program could then retrieve the database name and go and look for what has changed. Or for example, the program could automatically launch replication, if you don't want to use continuous_replication as exists in CouchDB 0.11.

Change notifications

CouchDB has the so-called _changes database-API which your application can use to get Comet-style notification of changes, be it by your application polling the database to query if anything has changed since a particular time or by CouchDB providing your application with a continuous stream of changes. I'm not going to delve into this API much, because it is very well documented in the book CouchDB: The Definitive Guide. In essence, you use an HTTP GET request to pull in a list of changed documents.

What I am going to dig into though, is how to tap that API with a JavaScript interface created by Mikeal Rogers on top of node.js. Now, if you are like I, when you hear JavaScript, you probably think of those pesky alert('hello'); or document.write('whatever'); on Web pages here and there. Well, times change: JavaScript has become a server-side language, and there is little it cannot do, as node.js very impressively demonstrates. (Disclaimer: I am neither a JavaScript nor a node.js specialist, so I may be doing something incorrectly here.)

Node.js

node.js is an evented I/O framework built by Ryan Dahl on Google's V8 JavaScript engine. It provides a very efficient system to create scalable and efficient applications without having to understand or use threading, processes, etc. In an event-based model you register what should happen, and node.js takes care of calling the callback function (you define) when the specific event happens. People who are used to programming JavaScript in a Web browser application (with, for example, jQuery), know this model well.

The event-based programming model is fundamental to JavaScript programming, and node.js leverages this model to programs that can handle massively concurrent events with little memory and processing power.

You'll have to install node.js, but doing so is easy. Once you have that running, come back and continue here.

node.couch.js

Mikeal Rogers created what he calls a generic change consumer that you can point at a running CouchDB instance. This change consumer, written in node.js periodically checks all CouchDB databases for existence of a changes field in the design documents of databases. If such a changes field is found, it must contain valid node.js code, which is pulled in by the consumer and executed on the machine running node.

What this means, is that once you have a consumer running, you can use Futon or CouchApp to create and modify code which is stored in your database design document, and that code is automatically read by the consumer and is triggerred by any PUT, POST or DELETE to documents in your database.

Prerequisites

A working node.js engine. Instructions for obtaining the source and building it are on the node.js site. (Google's V8 JavaScript engine is contained in node.js' source.)

A copy of node.couch.js. Actually, we need only the two files in changes/lib.

A CouchDB database you can play with, and a design document, named whatever you like.

You then launch node with the service.js script and point it to the URL of your CouchDB instance. It is important to note that node need not run on the same machine as your CouchDB instance: thanks to CouchDB's RESTful HTTP interface, it can obviously be queried from afar. Furthermore, all JavaScript and/or Node.js dependencies must be accessible on the machine running node (i.e. the client machine). I've wrapped the lot into a small executable I've called couchlisten.js:

So, what happens when I launch that program? node is executed and loads the required modules. The principal module is service, which then

Reads a list of all databases at the specified URI.

For each of the design documents, service tries to load the JavaScript contained in each of the changes fields. If the JavaScript code in the changes field contains an error, node will bail out and stop.

That JavaScript code sets up listeners to wait for document updates to actually occur.

service.js sets up an event to rescan CouchDB databases and design documents every 60 seconds.

Let me create a first design document called _design/app which contains the following JavaScript in the changes field:

I'll now start node on another window, and keep an eye on that, while we continue working here.

The first line with the JSON string is printed by the JSON.stringify() method -- useful for visualizing what our JavaScript has to work with. The second line (Hey: Jane) is printed by the second sys.puts().

Take particular note of the _deleted field, which allows me to differenciate whether I'm handling a real update or whether I should perhaps ignore this update notification as it is a deletion.

So far we've managed to create a minuscule JavaScript program contained in a CouchDB design document which is read by our node.js instance and executed whenever a document is added to (or deleted from) our CouchDB database.

Taking this a step further, let's see if we can actually do something with the updates.

Urgent tweets

Suppose I have a database into which messages (i.e. documents) are posted that may have a particular priority. I want to ensure that documents tagged with an "urgent" priority are notified to my Twitter account as soon as they are added to CouchDB.

The changes script in the design document now contains this JavaScript code, which relies on twitscript (a node.js module) to do the actual tweeting. In order to avoid update notifications for design documents, I check whether the document's ID is one of those.

I don't have to restart couchlisten.js, as it will pick up the modified design document momentarily.

Let me show you what the result looks like in the following screen cast, which consists of three windows:

The top window is where I'll be submitting requests to CouchDB, using resty.

The window in the center shows the output of our local node.js program, which I've called couchlisten.js.

In the bottom window, I have a small node.js program based on twitter-node. This program "follows" the Twitter user who is submitting the "urgent" Tweets.

And the result is quite pleasing:

And then?

CouchDB's changes API together with node.js and a bit of JavaScript open the potential to create exciting applications that react in real time to database modifications. I can use these update notifications for all sorts of interesting tasks:

I can use these update notifications to tally how many updates to a database have occurred, and then, initiate a backup to a remote site. (One that doesn't have CouchDB -- I'd otherwise use replication for that, wouldn't I? :-) )

If I use CouchDB as a writing platform, I can post via XML-RPC to my WordPress, Blogger, MT, etc. blog as soon as a document changes.

If I think "DNS" database, with a solution like my CouchDB pipe back-end to PowerDNS, I can use an update notification to send an alert e-mail to the domain's hostmaster, so that (s)he can verify the zone.

There is a lot to learn here, and I've only just started. For example, there is the CommonJS initiative which wants to create standardized modules for use in JavaScript. The good news? CouchDB supports this as well. There's also a lot more (for me) to learn about node.js, including the dozens of modules for it; these include Web servers, frameworks, database interfaces, templating systems, parsers, etc.