From 18a49da6b04e4a585f8d7d57573d330233c713c7 Mon Sep 17 00:00:00 2001 From: Skylar Ittner Date: Mon, 6 Dec 2021 23:18:39 -0700 Subject: [PATCH] Use incrementing version to reconcile setting sync conflicts instead of timestamp --- www/assets/js/storage.js | 7 +++--- www/assets/js/sync.js | 48 ++++++++++++++++++---------------------- www/settings.js | 4 ++-- 3 files changed, 28 insertions(+), 31 deletions(-) diff --git a/www/assets/js/storage.js b/www/assets/js/storage.js index 8e4c002..075056c 100644 --- a/www/assets/js/storage.js +++ b/www/assets/js/storage.js @@ -1,4 +1,4 @@ -/* +/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -9,7 +9,7 @@ * Save something to persistent storage. * @param {string} key * @param {string} value non-string values are converted to strings. - * @param {bool} nochangeupdate If true, the lastchange setting won't be updated. + * @param {bool} nochangeupdate If true, the settings version won't be updated. * @returns {undefined} */ function setStorage(key, value, nochangeupdate) { @@ -18,7 +18,8 @@ function setStorage(key, value, nochangeupdate) { } localStorage.setItem(key, value); if (!nochangeupdate && !SETTINGS.synckeyblacklist.includes(key)) { - localStorage.setItem("lastchange", Date.now() / 1000); + var version = getStorage("syncstateversion") == null ? 0 : getStorage("syncstateversion"); + localStorage.setItem("syncstateversion", Number(version) + 1); } } diff --git a/www/assets/js/sync.js b/www/assets/js/sync.js index d9bfe09..f6bcf94 100644 --- a/www/assets/js/sync.js +++ b/www/assets/js/sync.js @@ -6,15 +6,13 @@ function gatherSyncData() { + if (getStorage("syncstateversion") == null) { + setStorage("syncstateversion", 0); + } var data = { localStorage: {}, - changed: getStorage("lastchange") == null ? 0 : getStorage("lastchange"), + stateversion: getStorage("syncstateversion") == null ? 0 : getStorage("syncstateversion") }; - if (!inStorage("lastsync")) { - // first time syncing to the server, let's make sure - // the server settings take precedence - data.changed = 1; - } var allitems = getAllStorage(); for (var i = 0; i < allitems.length; i++) { var key = allitems[i].key; @@ -27,33 +25,30 @@ function gatherSyncData() { return data; } -function syncDataToLocalStorage(data) { +function syncDataToLocalStorage(data, stateversion) { for (var key in data.localStorage) { if (data.localStorage.hasOwnProperty(key)) { setStorage(key, data.localStorage[key], true); } } + setStorage("syncstateversion", stateversion); } -function resolveSync(remotedata) { - var localchangetime = getStorage("lastchange"); - if (remotedata.changed == null) { - // The server has nothing, this is the first sync - return true; - } - if (localchangetime == null) { - // No local setting changes but since we've gotten this far, - // the server has stuff for us - syncDataToLocalStorage(remotedata); +function resolveSync(remotedata, remotestateversion) { + var localstateversion = getStorage("syncstateversion"); + console.log("Resolving sync: remote state: " + remotestateversion, "local state: " + localstateversion); + if (localstateversion == remotestateversion) { + // Server and client both have same version + console.log("Sync: server is same as client"); return true; - } - if (localchangetime < remotedata.changed) { - // The server has newer stuff for us - syncDataToLocalStorage(remotedata); + } else if (Number(localstateversion) < Number(remotestateversion)) { + // Server has newer version + console.log("Sync: server is newer than client"); + syncDataToLocalStorage(remotedata, remotestateversion); return true; - } - if (localchangetime >= remotedata.changed) { - // Our local data is newer or the same as the server copy + } else { + // We have the newer version + console.log("Sync: client is newer than server."); return true; } return false; @@ -70,10 +65,11 @@ function syncNow(callback) { $.post(SETTINGS.syncapi, { username: username, password: password, - data: JSON.stringify(data) + data: JSON.stringify(data), + stateversion: data.stateversion }, function (resp) { if (resp.status == "OK") { - resolveSync(resp.data); + resolveSync(resp.data, resp.stateversion); setStorage("lastsync", Date.now() / 1000); if (typeof callback == "function") { callback(); diff --git a/www/settings.js b/www/settings.js index 3de9925..0886b90 100644 --- a/www/settings.js +++ b/www/settings.js @@ -367,7 +367,7 @@ var SETTINGS = { synckeyblacklist: [ "username", "password", "trackingcodehistory", "packages", "user_latitude", "user_longitude", "geocode_cache", "scanevents", - "lastsync", "lastchange" + "lastsync", "lastchange", "syncstateversion" ], geocodecacheexpiry: 604800, // One week geocodeapi: "https://apis.netsyms.net/packagehelper/geocode.php", @@ -377,7 +377,7 @@ var SETTINGS = { geoipapi: "https://data.netsyms.net/v1/net/geoip/key=packagehelper1/", sharelistapi: "https://apis.netsyms.net/packagehelper/sharepackagelist.php", loginurl: "https://apis.netsyms.net/packagehelper/login/", - syncapi: "https://apis.netsyms.net/packagehelper/sync.php", + syncapi: "https://apis.netsyms.net/packagehelper/sync_1.7.php", mapfixapi: "https://apis.netsyms.net/packagehelper/contribgeocode.php", addrlookupapi: "https://apis.netsyms.net/packagehelper/addresslookup.php" }