tomboy-notes / tomdroid

Tomboy notes on Android
https://play.google.com/store/apps/details?id=org.tomdroid
GNU Lesser General Public License v2.1
18 stars 14 forks source link

SYNC should not use date and time when comparing, but rather revision information #56

Open obilodeau opened 8 years ago

obilodeau commented 8 years ago

Clocks can be set wrongly, therefore using date and time to distinguish if a note needs to be pushed or pulled is maybe not a good idea. It would be better to use a "changed-locally" and "changed-on-server" tag for each note.

From the IRC with timo: j-4: Dynalon: does the server send anything to tell if the note changed? j-4: local note-changes can be tracked easily... but what about the remote ones? Dynalon: yes, the server will send all notes that have changed since the last sync. From what I recall when going through the tomdroid source, you don't use this feature however :-) You can add the ?since= parameter, it is documented in the API DOCs on https://live.gnome.org/Tomboy/Synchronization/REST/1.0 Dynalon: example: http://domain/api/1.0/user/notes?since=4 Dynalon: you would pass your "latest-sync-revision" field as argument to the since parameter Dynalon: when using the ?since= parameter, you SHOULD use ?since=4&include_notes=true - since you will definitely need the notes body content transfered Dynalon: but when checking for new/deleted notes, you can use ?include_notes=false which will disable transferring the notes content, only its metadata - this saved bandwidth

Documentation in the Tomboy library: https://github.com/Dynalon/tomboy-library/blob/sync_from_scratch/Tomboy-library/Tomboy/Sync/Sync.cs


Imported from Launchpad using lp2gh.

obilodeau commented 8 years ago

(by j-4) A separate "changed" tag ist not necessary. Tomdroid should work like Tomboy... see the explanation of Timo:

Dynalon: j-4: the global revision number is always selected by the sync server, and will be always the latest sync revision (server wise) + 1 Dynalon: you don't need to store revision-numbers per note, but those revision numbers are only valid locally. I suggest not calling them revision numbers. if you want to store locally when a note changed, jsut mark it as "tainted" Dynalon: whenever you do a successfull sync, reset all notes to "untainted". whenver you change a note locally, mark it as tainted again. This is only one possible approach Dynalon: the other one (that tomboy uses) is to not store tainting/local reivsion numbers at all, but make sure the MetadataChangeDate is updated whenver a note is updated Dynalon: you can then tell if a note was modified since last sync by selecting note.MetadataChangeDate > Manifest.LastSyncRevision Dynalon: since you are required to keep metadatachange date accurat on tomdroid, you could just use the later approach and don't need to deal with local per-note revision numbers Dynalon: anyway, you DO need to keep a list of notes that are deleted (since the notes won't be present upon next sync). AFAIK in tomdroid this is done using system:-Deleted tag, which is just fine

So we should raise the metadatachange whenever a note was edited and on sync obtain a list of edited notes by comparing note.MetadataChangeDate > Manifest.LastSyncRevision.

As easy as this :-)

obilodeau commented 8 years ago

(by noahy)

So we should raise the metadatachange whenever a note was edited and on sync obtain a list of edited notes by comparing note.MetadataChangeDate > Manifest.LastSyncRevision.

That's really what we do already, except we use last modified date to get the list.

obilodeau commented 8 years ago

(by j-4) yes and no.

this are the bad lines: int compareSyncLocal = Time.compare(syncDate, localNote.getLastChangeDate()); int compareSyncRemote = Time.compare(syncDate, remoteNote.getLastChangeDate()); int compareBoth = Time.compare(localNote.getLastChangeDate(), remoteNote.getLastChangeDate());

we are comparing a remote date with a local date -> very bad! This already led to the conflict-dialogue showing up without any conflicts and notes being pushed/pulled although they are identical,... just because of a small time difference of the clocks.

To know if a note was changed remotely, we should use this instead: example: http://domain/api/1.0/user/notes?since=4 you would pass your "latest-sync-revision" (=4) field as argument to the since parameter

To know if a note changed locally we can compare the lastsyncdate and the the MetadataChangeDate. Whats the difference between the lastchangedate and the MetadataChangeDate? MetadataChangeDate is also changed on a succesfull pull of the note from the server -> therefore it is always completely identical with the lastsync date. the lastchangedate could be wrong, as the clock from another client might be running different, so we can't compare these. Otherwise, on an edit, both are set identical. However, to implement it correctly, on an "NOT-content-change" like a tag-change, notebook-change, only the metadatachangedate should be raised, not the lastchangedate.

We know if a note might be conflicting, when note is in remotely changed list and has a metadatachangedate - lastsyncdate > 0.

For the SD-card sync we have to get the list of remotely changed notes since last sync somehow else. User might use Dropbox, therefore we also have to deal with conflicting notes and remotely changed ones. we could compare the lastchangedate of the files with the lastsyncdate, however the clock of the other Dropbox instance might run wrong again. better would be to remember a checksum, the changedate,... on one sync and compare this on the next sync to the values in the files -> therefore you would get a concrete list of changed files.

Do you understand the issue? I could try to explain it again in other words. Its not me, who found that this could be the issue for some 'weird' sync bugs I experienced, but Timo who programmed the Rainy Sync server as a replacement for Snowy. http://exceptionrethrown.wordpress.com/2012/11/04/announcing-rainy-a-poor-mans-tomboy-snyc-server/ He for sure knows how it is done... i hope :-)