Getting Things Done with CouchDB, part 1: how did I get here? |
2012-09-11
|
(... where I spend a whole post setting the scene)
Today is a day off in Barcelona - to some people it's a national holiday. To me, it's a big old opportunity to spend a whole day hacking on something I want to work on for myself.
And today, I wanted to go back to hack on mushin. What is mushin, you ask? I thought you'd never. It's going to take all of this post to explain, and I won't even get to today's hack part.
mushin is an application to implement the Getting Things Done approach. I follow this approach with varying degrees of success, but it's what has worked best for me so far.
I was never really happy with any of the tools available that claimed to implement it. For me, the basic requirements are:
- available off-line (no online-only solutions)
- data available across devices. I use my laptop, home desktop, and work desktop regularly; and when I'm in the store and I only have my phone with me I want to be able to see what I was supposed to buy whenever I'm in the @shopping context)
- easy to add new tasks; preferably a command-line. I add tasks during meetings, when I'm on the phone, when I'm talking to someone, or simply typing them on my phone, so it has to be easy and quick.
This excluded many solutions at the time I first started looking for one. I recall RememberTheMilk was popular at the time, but since I was spending at least four hours a week on plane trips back then, and planes were excellent places to do GTD reviewing, it was simply not an option for me.
I don't know if Getting things GNOME already existed back then. When I first looked at it, it was basically a local-only application, but since then it's evolved to letting you synchronize tasks online, although it still looks like it's an added-on feature instead of an integral design choice. I should try it again someday.
Anyway, I ended up using yagtd, which is a command-line application operating on a text file. I put the text file in subversion, and then proceeded to use it across three computers (back then I did not have a real smartphone yet), and cursing every time I forgot to update from subversion or commit to subversion. At least the conflicts were usually easy to manage since yagtd basically stores one line per 'thing'.
And then I discovered CouchDB and I did what they told me to - I relaxed. I created a personal project called 'things' that took most of yagtd's functionality but put all the data in CouchDB. CouchDB solved two of the three requirements of my list above - it promised to make it possible to have my data available locally, even when offline, and to be able to synchronize it across devices. (Of course, I later figured out that it's nice in theory but not that simple in practice - but the basics are there)
Even though I really liked the name 'things', because, you know, if you're writing a GTD application, the things you are doing are actually, 'things'. But I realized it was a stupid ungoogleable name, so I ended up going for something Japanesey that was close enough to 'mind like water' and stumbled on the name 'mushin' - (bonus: it started with an m, and for some reason I'm accumulating personal projects that start with m)
So I happily hacked away on mushin, making it have the same featureset as yagtd, but with couchdb as the backend. Originally I used python-couchdb, since for a command-line application it's not strictly necessary to write non-blocking code. This was almost three years ago, and I've been using this application pretty much every day since then. (In fact, I have 2153 open things to do, and a well-rested mind that typically isn't too concerned about forgetting about stuff, because everything I need to worry about is *somewhere* in those 2153 open things. And some days that statement is truer than on others!)
I wonder how many people by now think I'm a classic case of NIH - surely lots of people are happily using tools for GTD already. The way I convinced myself that it made sense to create this tool is because I was incredibly excited about the promise of CouchDB (and I still am, although I 'm confused about what's going on in CouchDB land, but more on that in another post).
Maybe I was a rarity back then, with my work desktop in Barcelona, my laptop, and my home desktop in Belgium, and wanting my data in all three, all the time. In the back of my mind I was still planning to write the Ultimate Music Application, with automatic synchronization of tracks and ratings synchronized across devices, and I thought that a simple GTD application would be an excellent testing ground to see if CouchDB really could deliver on the promises it was making to my future self.
Over time, I adapted mushin. At some point, I got an N900, and I wanted mushin to work on it, and a command-line client didn't make that much sense. So I wrote a GUI frontend for it, and it was time to port mushin over to use Twisted, so that all calls could be done asynchronously and integrate nicely with the GUI. I switched from python-couchdb to Paisley, a CouchDB client from Twisted. (At one time I was even tricked into thinking I was the maintainer, appointed by the previous maintainer according to the last-touched rule, but then someone else happily forked Paisley from under me, and it now lives on github. I copied over the python-couchdb Document/Schema/Mapping code, because I liked how it worked.
And there I had a Maemo client, using most of the same code, and with access to the same data as all my desktops and laptop. I had reached my requirements, in a fashion.
It wasn't ideal: replication had to be triggered manually. I had a command to do so, but any restart of a couchdb server, or being offline too long (a few hours of my laptop not being online or even on, for example) would break the replication. In practice, you still somehow need to initiate the replication, or write code around that to do that for you. Especially with my phone, which I usually don't have online, it's easy to forget and find yourself at the store without having synced first and not remembering exactly what it was I was supposed to buy. But it was good enough.
But I never really mentioned anything about his project, and the reason was simple. I was using CouchDB in Admin Party mode (anyone can do anything), and to be able to replicate (without fiddling with tunnels and the like) I had couchdb listening on 0.0.0.0 So if anyone had known I was using this tool, it would have been very easy to take a look at all my tasks (bad), assign me some new tasks (even worse), or, you know, drop my whole database of things (I used to think that was bad, but today I'm not so convinced anymore?)
So I decided to rely on security by obscurity, and never write about my GTD application.
But now I did, so if you're still with me, you may be excited about the prospect of getting onto a network of mine and dropping my database, to release me from the mental pressure of 2153 things to be done?
Ah, well... That's what part 2 is going to be about. Stay tuned.
In the meantime, I converted my SVN repository to git and threw it on github. I only run it uninstalled at the moment, not ready yet to be packaged, but hey, if you're brave... have a go.
is it possible to search in GTG?
Comment by pt — 2012-09-12 @ 02:36
have you considered “replicating” plaintext files by means of something like dropbox or git? (there should be a way to use git and not have merge conflicts)
Comment by Dieter — 2012-09-12 @ 08:22
Yes, I have, but I think it would still be suboptimal. I don’t know how Dropbox manages conflicts, but I assume it would end up letting you retrieve conflicting versions from the web interface, so that wouldn’t be ideal if all you did was simply add two different tasks on two different machines. CouchDB wouldn’t even see that as a conflict, since they are different documents in a database, as opposed to two new lines in one data file. CouchDB, when it does have conflicts, picks the same winner everywhere, and then makes it easy to look at conflicts, so it would be possible to resolve them programatically.
git would have been an option too, but I never liked the model I had going with yagtd and subversion where you need to remember to commit; in git you would have to commit and push. Granted, this could be scripted. conflicts in text files would still have to be resolved by hand, and typically the problem is as I said adding tasks on different machines. git would leave this as a conflict to be resolved manually because of the way diff and patch work.
CouchDB just has a much more natural model on which to base conflict resolution.
Comment by Thomas — 2012-09-12 @ 10:50
Really insteresting. Any “screenshots” somewhere?
Something I did not understand: why developping a client-server application? Why not embbeding the whole application in CouchDB?
I played with CouchDB and did some “Hello world” application. It was funny to create a whole JavaScript application embedded in the database.
I imagined something like a cross between CouchDB and GTDTiddlyWiki: a quite simple but still rich web application but run by a CouchDB application (and not inside a browser).
Comment by Guyou — 2012-09-14 @ 15:49
to avoid conflicts, you can:
* use a custom git merge driver (my favorite option)
* even the default union merge driver should work too, unless you explicitly write auto-increment integer id’s to your entries (which would cause duplicate id’s) but you can fairly easily avoid this.
* write different tasks in different files.
Comment by Dieter — 2012-09-15 @ 20:05
I would recommend checking out Gtdagenda.com for an online task & project manager.
You can use it to manage your goals, projects and tasks, set next actions and contexts, use checklists, and a calendar.
Syncs with Evernote, and also comes with mobile-web version, and Android and iPhone apps.
Comment by Dan — 2012-09-18 @ 15:26