SQL layout of the `syncroton_synckey` table
CREATE TABLE `syncroton_synckey` ( `id` varchar(40) NOT NULL, `device_id` varchar(40) NOT NULL DEFAULT , `type` varchar(64) NOT NULL DEFAULT , `counter` int(11) unsigned NOT NULL DEFAULT '0', `lastsync` datetime DEFAULT NULL, `pendingdata` longblob, PRIMARY KEY (`device_id`,`type`,`counter`), CONSTRAINT `syncroton_synckey::device_id--syncroton_device::id` FOREIGN KEY (`device_id`) REFERENCES `syncroton_device` (`id`) ON DELETE CASCADE ON UPDATE CASCADE );
Each Sync command send by the client has a unique SyncKey. At the beginning of each Sync command, Syncroton validates this SyncKey using the function validate($_deviceId, $_folderId, $_syncKey). If the SyncKey can be validated, the Sync command continues as requested. If not, it will signal the client, that he has to forget any content sent by the server and must start the synchronisation process from the beginning. In this case all stored syncstates for the folder have to be deleted via resetState($_deviceId, $_folderId).
If the Sync command was successful and any data got changed the SyncKey will be incremented by one and the new syncstate will be added to the syncroton_synckey table with create(Syncroton_Model_ISyncState $_syncState, $_keepPreviousSyncState = true). If no data got send to the client, the SyncKey stays the same and the syncstace will be updated via update(Syncroton_Model_ISyncState $_syncState).
As any new SyncKey will be added to the syncroton_synckey, we could store all previous SyncKey's. But we don't them. We only need to last two. We store the last two, because it is very likely, that our last response was not received by the client. If the client lost network connectivity, while we send the reponse, the client can not not receive our new SyncKey. The client will send the next Sync command with the previous SyncKey stored in our database.
At the beginning on any Sync command we call the function validate($_deviceId, $_folderId, $_syncKey). This function is responsible for validating the SyncKey send by the client against the last or previous SyncKey stored in the syncroton_synckey table. If the client sends really the last SyncKey, all information stored of the previous SyncKey will be deleted from syncroton_synckey and syncope_content. if the client sends the previous SyncKey, he did not receive our last response and we have to roll back any information stored during the last (not successful) synchronisation.
This way we can recover from lost Sync command responses without the need to start the synchronisation from the beginning again.
There is one case, where can't recover from a lost Sync command response. When the client added new content (for example an event) we can't recover. As the event got stored in the database already and the invitation got send out, we simply can't delete the event and create it as new. Fortunately this happens very seldom.
getSyncState($_deviceId, $_folderId) returns the latest SyncKey for a given device and folder.
The get function requests a syncstate object be it's internal id.
To summarize the logic. After the Sync command finished we may have two SyncKey's stored. When Syncroton processes the next Sync command, the validate function will delete one of them and commit or roll back the changes done during the previous Sync command.