From 66b0e4b643ca1d063a6f3332d21991dd197a63be Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Fri, 17 Nov 2023 14:01:02 +0000 Subject: [PATCH] Restructure syncer to use a single state machine --- core/modules/syncer.js | 223 ++++++++++++++++++++++------------------- 1 file changed, 121 insertions(+), 102 deletions(-) diff --git a/core/modules/syncer.js b/core/modules/syncer.js index d4eaa8f77..58b087b8d 100644 --- a/core/modules/syncer.js +++ b/core/modules/syncer.js @@ -24,7 +24,7 @@ Syncer.prototype.titleSyncPollingInterval = "$:/config/SyncPollingInterval"; Syncer.prototype.titleSyncDisableLazyLoading = "$:/config/SyncDisableLazyLoading"; Syncer.prototype.titleSavedNotification = "$:/language/Notifications/Save/Done"; Syncer.prototype.titleSyncThrottleInterval = "$:/config/SyncThrottleInterval"; -Syncer.prototype.taskTimerInterval = 1 * 1000; // Interval for sync timer +Syncer.prototype.taskTimerInterval = 0.25 * 1000; // Interval for sync timer Syncer.prototype.throttleInterval = 1 * 1000; // Defer saving tiddlers if they've changed in the last 1s... Syncer.prototype.errorRetryInterval = 5 * 1000; // Interval to retry after an error Syncer.prototype.fallbackInterval = 10 * 1000; // Unless the task is older than 10s @@ -74,9 +74,11 @@ function Syncer(options) { this.titlesHaveBeenLazyLoaded = {}; // Hashmap of titles of tiddlers that have already been lazily loaded from the server // Timers this.taskTimerId = null; // Timer for task dispatch - this.pollTimerId = null; // Timer for polling server // Number of outstanding requests this.numTasksInProgress = 0; + // True when we want to force an immediate sync from the server + this.forceSyncFromServer = false; + this.timestampLastSyncFromServer = new Date(); // Listen out for changes to tiddlers this.wiki.addEventListener("change",function(changes) { // Filter the changes to just include ones that are being synced @@ -300,91 +302,8 @@ Syncer.prototype.getStatus = function(callback) { Synchronise from the server by reading the skinny tiddler list and queuing up loads for any tiddlers that we don't already have up to date */ Syncer.prototype.syncFromServer = function() { - var self = this, - cancelNextSync = function() { - if(self.pollTimerId) { - clearTimeout(self.pollTimerId); - self.pollTimerId = null; - } - }, - triggerNextSync = function() { - self.pollTimerId = setTimeout(function() { - self.pollTimerId = null; - self.syncFromServer.call(self); - },self.pollTimerInterval); - }, - syncSystemFromServer = (self.wiki.getTiddlerText("$:/config/SyncSystemTiddlersFromServer") === "yes" ? true : false); - if(this.syncadaptor && this.syncadaptor.getUpdatedTiddlers) { - self.logger.log("Retrieving updated tiddler list"); - cancelNextSync(); - this.syncadaptor.getUpdatedTiddlers(self,function(err,updates) { - triggerNextSync(); - if(err) { - self.displayError($tw.language.getString("Error/RetrievingSkinny"),err); - return; - } - if(updates) { - $tw.utils.each(updates.modifications,function(title) { - self.titlesToBeLoaded[title] = true; - }); - $tw.utils.each(updates.deletions,function(title) { - if(syncSystemFromServer || !self.wiki.isSystemTiddler(title)) { - delete self.tiddlerInfo[title]; - self.logger.log("Deleting tiddler missing from server:",title); - self.wiki.deleteTiddler(title); - } - }); - if(updates.modifications.length > 0 || updates.deletions.length > 0) { - self.processTaskQueue(); - } - } - }); - } else if(this.syncadaptor && this.syncadaptor.getSkinnyTiddlers) { - this.logger.log("Retrieving skinny tiddler list"); - cancelNextSync(); - this.syncadaptor.getSkinnyTiddlers(function(err,tiddlers) { - self.logger.log("Retrieved skinny tiddler list"); - triggerNextSync(); - // Check for errors - if(err) { - self.displayError($tw.language.getString("Error/RetrievingSkinny"),err); - return; - } - // Keep track of which tiddlers we already know about have been reported this time - var previousTitles = Object.keys(self.tiddlerInfo); - // Process each incoming tiddler - for(var t=0; t= (this.timestampLastSyncFromServer.valueOf() + this.pollTimerInterval)))) { + return new SyncFromServerTask(this); + } + // Third, we check tiddlers that are known from the server but not currently in the store, and so need deleting on the server titles = Object.keys(this.tiddlerInfo); for(index=0; index