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:
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
So you could rename
Car Radios with just a simple change. That tag would change in the database to look like this:
name: Car Radios
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:
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 have the same uniqueID.)
This solves the day/night phone problem like this:
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
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.
(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:
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.
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.