Revision 12 as of 2011-04-16 02:24:58

Clear message

This is where I'm keeping my notes on changes I would like to see in desktopcouch based on my experience working on dmedia. Note that this is written out of love of desktopcouch, despite being a list of pain points I would like to see changed.

May Stuart and Jason's bromance continue.

Abstract away the Desktop part

In addition to using desktopcouch, Both Novacut and dmedia must be able to run on headless servers and talk to a system-wide CouchDB. Although as of dmedia 0.6 this will finally be possible, it took a while to get there, plus there is still one fundamental issue: the desktopcouch reconnection hack for working around CouchDB crashing after resuming from suspend.

Ideally, the standard way of using desktopcouch should abstract out the desktop part, so that apps can easily run with desktopcouch or standalone CouchDB, without each app rolling its own abstraction.

reconnection hack must go

To have the reconnection hack work you must use a desktopcouch.records.database.Database, which makes it basically impossible to abstract away the desktop.

My #1 request for Oneiric is for this to change. Instead, the port must remain the same throughout the desktop session. It's fine if the port is randomly chosen at the start of the session, but it must remain the same once desktopcouch starts.

When it comes down to it, the API needs to be plain HTTP. Requiring a specialized wrapper library like desktopcouch closes off too many cool use cases (like having the same app run both on the web and on desktopcouch more or less transparently).

For what it's worth, desktopcouch.Database isn't close enough to the CouchDB REST API to be usable by dmedia (DC makes too many assumptions, certain functionality isn't available). In fact, even python-couchdb has been a constant headache for dmedia... again, certain functionality isn't exposed, and there is way too much magic/ambiguity behind the scenes.

Not that this sort of wrapper isn't probably a perfect fit for some applications. But dmedia and Novacut are pretty demanding, and something close to the metal like microfiber would make my life much easier.


As discussed in lp:722035, there needs to be a single entry point from which an app can get information about the CouchDB environment it is running in. If you were running against desktopcouch, it would return something like this:

  • {
      "oauth": {
        "consumer_key": "oRTyTHKiKu", 
        "consumer_secret": "bdXSzITryM", 
        "token": "lyrygLlsbk", 
        "token_secret": "QbqvZaiBGV"
      "port": 45484, 
      "url": "http://localhost:45484/"

Or if you were running against the system-wide CouchDB, it would return something like this:

  • {
      "port": 5984, 
      "url": "http://localhost:5984/"

dmedia.core.get_env() implements the above behavior (but the point is apps shouldn't have to abstract away the desktop part on their own).

When talking to CouchDB from Python, dmedia.abstractcouch.get_server() is used to create an appropriately configured couchdb.Server based on the env it is passed.

When talking to CouchDB from JavaScript (UI running in embedded WebKit), the dmedia CouchView is used to transparently sign OAuth requests. This would be a great piece to standardize and upstream into desktopcouch.

enforcing record_type is too restrictive

Although the record_type convention addresses an important need (standardizing document schema for use across apps), it's rather awkward and verbose. In dmedia/Novacut, the type (or record_type) needs to be referenced very often, and in many contexts (view functions, UI code, etc), so I've needed something more concise.

For example, the desktopcouch spec dictates something like this:

  • {
        "record_type": ""

But dmedia uses something much less verbose:

  • {
        "type": "dmedia/file"

This is a very typical dmedia view function:

  • function(doc) {
        if (doc.type == 'dmedia/file') {
            emit(doc.mtime, null);

Which becomes awkward and far less readable if using the desktopcouch convention:

  • function(doc) {
        if (doc.record_type == '') {
            emit(doc.mtime, null);

Per DB sync should be opt-in, not opt-out

Developing with desktopcouch I've found it annoying that all the databases are synced to UbuntuOne by default... I frequently create test databases for testing dmedia (not just unit tests, but also using dmedia for an extended period, while not wanting to hose up my production dmedia DB). UbuntuOne sync is, of course, 100% awesome, but having it op-in rather than opt-out would make life easier for developers. It also avoids potential unexpected privacy oopses... when I was first learning desktopcouch I was surprised everything was synced by default. In my case, nothing in the database was sensitive, but for some, that wont be the case.

So, in reverse order of preference, the solution I would like is:

  • At the very least, desktopcouch should not sync databases whose names start with test_

  • Change from opt-out to opt-in, eg have included_names rather than excluded_names

  • Preferably, the included_names list should be stored in a non-replicated _local/foo document, or local file

The last point needs some explanation. Currently the opt-out list is stored in a replicated document in the management database, which syncs through UbuntuOne to all devices. This means that all devices get the same set of databases, which doesn't always make sense as not all devices will have the apps that use those databases. This is particularly an issue with mobile devices, when syncing unnecessary databases will needlessly burn through precious storage, bandwidth, and CPU time. Note that tablets in particular are a very high priority for Novacut.

There is also a security and privacy issue here. Whether opt-in or opt-out, if this critical decision is stored in a replicated document, an attacker need only gain control of a single device or service to cause other devices to replicate databases intended to be local-only.

Make web apps first class citizens

dmedia and Novacut make heavy use of an architecture like this:


The idea is that a large part of the user experience is implemented as an HTML5 UI, which can run as a native app in embedded WebKit, or be delivered over the web to standard browsers. When running as a native app, we're integrating with all the Ayatana niceties, so the experience isn't exactly the same, but close. Although certainly not the only way to take advantage of desktopcouch, running in embedded WebKit has some big advantages:

  • Can build a very snappy UI by making XMLHttpRequest directly to CouchDB, dynamically updating DOM
  • A plastic tool that gives designers sweeping freedom, yet allows quick implementation
  • Can build reusable user experiences consumable both in native apps and over the web

With help from Stuart Langridge, I have the dmedia CouchView working as a nice proof of concept. Importantly, CouchView will transparently sign the OAuth requests when connecting the desktopcouch, plus works equally well connecting to the system wide CouchDB.

Standard location for static webUI files