inessential by Brent Simmons

Vesper Sync Diary #1 - Syncing Tags

Because we announced that we’re working on syncing, I have the luxury and fun of being able to narrate my work.

I’m thinking about syncing tags.

My first thought is to assign each tag a unique ID (a UUID). This has the advantage that if a tag is renamed (not promising that feature), then it’s easy to sync that name change. Tags might look like this in the database:

name: Cars
uniqueID: 436BF0FC-E264-45EC-​ACD9-C1A363845FC7

name: Radios
uniqueID: A758512C-7B20-4F5F-9C4B-B40BE0BC2220

And then a note would refer to its tags via an array of uniqueIDs. Something like this…

tags: 436BF0FC-E264-45EC-​ACD9-C1A363845FC7, A758512C-7B20-4F5F-​9C4B-B40BE0BC2220

…would translate to Cars, Radios.

So you could rename Radios to Car Radios with just a simple change. That tag would change in the database to look like this:

name: Car Radios
uniqueID: A758512C-7B20-4F5F-​9C4B-B40BE0BC2220

And the note wouldn’t have to change, since the unique IDs of its tags haven’t changed. All that’s changed is the name field. Nice.

But here’s the problem

You have a day phone and a night phone. (Imagine.)

You’re thinking about your upcoming trip to Paris. On your day phone you create a Paris tag. But your day phone is off-line, and you switch to your night phone before your day phone gets the chance to sync.

So now it’s night-time, and you’re still thinking about your upcoming trip to Paris. On your night phone you create a Paris tag too.

Now you’ve got this situation with tags:

Day phone
name: Paris
uniqueID: 92B6E1D4-C49A-4D74-​A0C3-C120B67EE5E9
Night phone
name: Paris
uniqueID: B0F4EFD6-9953-4CFD-​ADBB-FE1CFAFD22D3

That’s really two separate tags, since they’re referenced by uniqueID instead of name. Notes on your day phone refer to 92B6E1D4-C49A-4D74-​A0C3-C120B67EE5E9; notes on your night phone refer to B0F4EFD6-9953-​4CFD-ADBB-FE1CFAFD22D3.

I don’t like that. You don’t like that.

How I think I will solve the problem

Instead I’ll give each tag a uniqueID that changes when the name changes. The uniqueID will be the name transformed to lower-case. (So that Paris and paris have the same uniqueID.)

This solves the day/night phone problem like this:

Day phone
name: Paris
uniqueID: paris
Night phone
name: Paris
uniqueID: paris

Same! Cool.

This makes renaming tags more difficult, though. In this scenario, a note’s list of tags looks like this:

tags: cars, radios

So when you rename Radios to Car Radios, it’s necessary to update every single note that references radios so that it looks like this:

tags: cars, car radios

That’s more work when renaming, but I think the trade-off is worth it so that your day and night phones don’t clash when you create the same tag on each device before they sync.

But what about deleting tags?

(Not promising this feature either, but I have to code for it.)

After your trip to Paris you delete the Paris tag. One way to handle this is to make the tag entry look like this:

name: Paris
uniqueID: paris
deleted: YES

Just flip the deleted bit to YES, and that’s the entire change. The app would be smart enough to know that if a note refers to the Paris tag, it should just ignore it, not show it, since that tag has been deleted.

One small change and you’re done. Nice.

But no…

Six months later you have another trip to Paris. So you’re writing a note and give it a Paris tag. What should happen then?

Well, we could flip deleted back to NO. But then all the notes from your previous trip would all of a sudden have their Paris tag resurrected.

You don’t want that, because you’d deleted the Paris tag back then. You just want new notes tagged with Paris to show that tag.

How I think I will solve the deleting problem

The right thing to do is, once again, more work. The app will visit all the notes that refer to that tag, and remove that reference.

If a note has tags like this…

tags: paris, packing, travel

…then it would be changed to look like this:

tags: packing, travel

The actual tag could remain in the database — it’s just that no notes would refer to it. In the case of tags, that’s the equivalent of deleting it.

And if you started using that tag again in the future, it would, correctly, appear just for new notes. It wouldn’t get resurrected for old notes, since those notes were changed to not refer to that tag.


I’m still thinking about tags. I could change my mind (particularly if I think of a better way, or if someone tells me about a better way).

Much of the rest of syncing is conceptually nailed down. (Much of it was nailed down before I wrote the first line of Vesper code last February.) But things can change as theory meets code.