Преглед на файлове

Начало очередной переделки ServerStorage

Book Pauk преди 5 години
родител
ревизия
7853a14ce6
променени са 2 файла, в които са добавени 114 реда и са изтрити 156 реда
  1. 114 143
      client/components/Reader/ServerStorage/ServerStorage.vue
  2. 0 13
      client/components/Reader/share/bookManager.js

+ 114 - 143
client/components/Reader/ServerStorage/ServerStorage.vue

@@ -13,6 +13,11 @@ import readerApi from '../../../api/reader';
 import * as utils from '../../../share/utils';
 import * as cryptoUtils from '../../../share/cryptoUtils';
 
+import localForage from 'localforage';
+const ssCacheStore = localForage.createInstance({
+    name: 'ssCacheStore'
+});
+
 export default @Component({
     watch: {
         serverSyncEnabled: function() {
@@ -58,35 +63,52 @@ class ServerStorage extends Vue {
 
     async init() {
         try {
+            this.cachedRecent = await ssCacheStore.getItem('recent');
+            if (!this.cachedRecent)
+                await this.setCachedRecent({rev: 0, data: {}});
+
+            this.cachedRecentPatch = await ssCacheStore.getItem('recent-patch');
+            if (!this.cachedRecentPatch)
+                await this.setCachedRecentPatch({rev: 0, data: {}});
+
+            this.cachedRecentMod = await ssCacheStore.getItem('recent-mod');
+            if (!this.cachedRecentMod)
+                await this.setCachedRecentMod({rev: 0, data: {}});
+
             if (!this.serverStorageKey) {
                 //генерируем новый ключ
                 await this.generateNewServerStorageKey();
             } else {
                 await this.serverStorageKeyChanged();
             }
+
             bookManager.addEventListener(this.bookManagerEvent);
         } finally {
             this.inited = true;
         }
     }
 
+    async setCachedRecent(value) {
+        await ssCacheStore.setItem('recent', value);
+        this.cachedRecent = value;
+    }
+
+    async setCachedRecentPatch(value) {
+        await ssCacheStore.setItem('recent-patch', value);
+        this.cachedRecentPatch = value;
+    }
+
+    async setCachedRecentMod(value) {
+        await ssCacheStore.setItem('recent-mod', value);
+        this.cachedRecentMod = value;
+    }
+
     async bookManagerEvent(eventName, itemKey) {
         if (!this.serverSyncEnabled)
             return;
 
         if (eventName == 'recent-changed') {            
             if (itemKey) {
-                if (!this.recentDeltaInited) {
-                    await this.loadRecent();
-                    this.warning('Функции сохранения на сервер пока недоступны');
-                    return;
-                }
-
-                if (!this.recentDelta)
-                    this.recentDelta = {};
-
-                this.recentDelta[itemKey] = _.cloneDeep(bookManager.recent[itemKey]);
-
                 this.debouncedSaveRecent(itemKey);
             }
         }
@@ -340,46 +362,26 @@ class ServerStorage extends Vue {
         }
     }
 
-    async initRecentDelta() {
-        let recentDelta = null;
-        try {
-            recentDelta = await this.storageGet({recentDelta: {}});
-        } catch(e) {
-            this.error(`Ошибка соединения с сервером: ${e.message}`);
-            return;
-        }
-
-        if (recentDelta.state == 'success') {
-            recentDelta = recentDelta.items.recentDelta;
-
-            if (recentDelta.rev == 0)
-                recentDelta.data = {};
-
-            this.recentDelta = recentDelta.data;
-            this.recentDeltaInited = true;
-        } else {
-            this.warning(`Неверный ответ сервера: ${recentDelta.state}`);
-        }
-    }
-
     async loadRecent(skipRevCheck = false, doNotifySuccess = true) {
         if (!this.keyInited || !this.serverSyncEnabled || this.loadingRecent)
             return;
-
         this.loadingRecent = true;
         try {
-            const oldRecentRev = bookManager.recentRev;
-            const oldRecentDeltaRev = bookManager.recentDeltaRev;
             //проверим ревизию на сервере
+            let query = {recent: {}, recentPatch: {}, recentMod: {}};
             let revs = null;
             if (!skipRevCheck) {
                 try {
-                    revs = await this.storageCheck({recent: {}, recentDelta: {}});
-                    if (revs.state == 'success' && revs.items.recent.rev == oldRecentRev &&
-                        revs.items.recentDelta.rev == oldRecentDeltaRev) {
-                        if (!this.recentDeltaInited)
-                            await this.initRecentDelta();
-                        return;
+                    revs = await this.storageCheck(query);
+                    if (revs.state == 'success') {
+                        if (revs.items.recent.rev != this.cachedRecent.rev) {
+                            //no changes
+                        } else if (revs.items.recentPatch.rev != this.cachedRecentPatch.rev) {
+                            query = {recentPatch: {}, recentMod: {}};
+                        } else if (revs.items.recentMod.rev != this.cachedRecentMod.rev) {
+                            query = {recentMod: {}};
+                        } else
+                            return;
                     }
                 } catch(e) {
                     this.error(`Ошибка соединения с сервером: ${e.message}`);
@@ -389,44 +391,45 @@ class ServerStorage extends Vue {
 
             let recent = null;
             try {
-                recent = await this.storageGet({recent: {}, recentDelta: {}});
+                recent = await this.storageGet(query);
             } catch(e) {
                 this.error(`Ошибка соединения с сервером: ${e.message}`);
                 return;
             }
 
             if (recent.state == 'success') {
-                let recentDelta = recent.items.recentDelta;
-                recent = recent.items.recent;
-
-                if (recent.rev == 0)
-                    recent.data = {};
-
-                let newRecent = {};
-                if (recentDelta && recentDelta.data) {
-                    if (recentDelta.data.diff) {
-                        newRecent = recent.data;
-                        const key = recentDelta.data.diff.key;
-                        if (newRecent[key])
-                            newRecent[key] = utils.applyObjDiff(newRecent[key], recentDelta.data.diff);
-                    } else {
-                        newRecent = Object.assign(recent.data, recentDelta.data);
-                    }
-                    this.recentDelta = recentDelta.data;
-                } else {
-                    newRecent = recent.data;
-                    this.recentDelta = {};
-                }
-
-                this.recentDeltaInited = true;
+                let newRecent = recent.items.recent;
+                let newRecentPatch = recent.items.recentPatch;
+                let newRecentMod = recent.items.recentMod;
+
+                if (!newRecent)
+                    newRecent = _.cloneDeep(this.cachedRecent);
+                if (!newRecentPatch)
+                    newRecentPatch = _.cloneDeep(this.cachedRecentPatch);
+                if (!newRecentMod)
+                    newRecentMod = _.cloneDeep(this.cachedRecentMod);
+
+                if (newRecent.rev == 0) newRecent.data = {};
+                if (newRecentPatch.rev == 0) newRecentPatch.data = {};
+                if (newRecentMod.rev == 0) newRecentMod.data = {};
+
+                let result = Object.assign({}, newRecent.data, newRecentPatch.data);
+                if (newRecentMod.key && result[newRecentMod.key])
+                    result[newRecentMod.key] = utils.applyObjDiff(result[newRecentMod.key], newRecentMod.mod);
+
+                if (newRecent.rev != this.cachedRecent.rev)
+                    await this.setCachedRecent(newRecent);
+                if (newRecentPatch.rev != this.cachedRecentPatch.rev)
+                    await this.setCachedRecentPatch(newRecentPatch);
+                if (newRecentMod.rev != this.cachedRecentMod.rev)
+                    await this.setCachedRecentMod(newRecentMod);
 
                 if (!bookManager.loaded) {
                     this.warning('Ожидание загрузки списка книг перед синхронизацией');
                     while (!bookManager.loaded) await utils.sleep(100);
                 }
-                await bookManager.setRecent(newRecent);
-                await bookManager.setRecentRev(recent.rev);
-                await bookManager.setRecentDeltaRev(recentDelta.rev);
+
+                await bookManager.setRecent(result);
             } else {
                 this.warning(`Неверный ответ сервера: ${recent.state}`);
             }
@@ -444,91 +447,59 @@ class ServerStorage extends Vue {
 
         const bm = bookManager;
 
-        //вычисление критерия сохранения целиком
-        if (!this.sameKeyCount)
-            this.sameKeyCount = 0;
-        if (this.prevItemKey == itemKey) {
-            this.sameKeyCount++;
-        } else {
-            this.sameKeyCount = 0;
-        }
+        let needSaveRecent = false;
+        let needSaveRecentPatch = false;
+        let needSaveRecentMod = true;
 
-        const l = Object.keys(this.recentDelta).length - (1*(!!this.recentDelta.diff));
-        this.makeDeltaDiff = (l == 1 && this.prevItemKey == itemKey ? this.makeDeltaDiff : false);
-        const forceSaveRecent =  l > 20 || (this.sameKeyCount > 5 && (l > 1)) || (l == 1 && this.sameKeyCount > 10 && !this.makeDeltaDiff);
-
-        this.sameKeyCount = (!forceSaveRecent ? this.sameKeyCount : 0);
-        this.prevItemKey = itemKey;
-
-        //дифф от дельты для уменьшения размера передаваемых данных в частном случае
-        if (this.makeDeltaDiff) {
-            this.recentDelta.diff = utils.getObjDiff(this.prevSavedItem, bm.recent[itemKey]);
-            this.recentDelta.diff.key = itemKey;
-            delete this.recentDelta[itemKey];
-        } else if (this.recentDelta.diff) {
-            const key = this.recentDelta.diff.key;
-            if (!this.prevSavedItem && bm.recent[key])
-                this.prevSavedItem = _.cloneDeep(bm.recent[key]);
-            if (this.prevSavedItem) {
-                this.recentDelta[key] = utils.applyObjDiff(this.prevSavedItem, this.recentDelta.diff);
-            }
-            delete this.recentDelta.diff;
+        let newRecentMod = _.cloneDeep(this.cachedRecentPatch);
+        newRecentMod.rev++;
+
+        let newRecentPatch = _.cloneDeep(this.cachedRecentPatch);
+        newRecentPatch.data[itemKey] = bm.recent[itemKey];
+        newRecentPatch.rev++;
+        needSaveRecentPatch = true;
+
+        let newRecent = {rev: this.cachedRecent.rev + 1, data: bm.recent};
+
+        let query = {};
+        if (needSaveRecent) {
+            query = {recent: newRecent, recentPatch: newRecentPatch, recentMod: newRecentMod};
+        } else if (needSaveRecentPatch) {
+            query = {recentPatch: newRecentPatch, recentMod: newRecentMod};
+        } else {
+            query = {recentMod: newRecentMod};
         }
 
         //сохранение
         this.savingRecent = true;        
         try {
-            if (forceSaveRecent) {//сохраняем recent целиком
-                let result = {state: ''};
-
-                try {
-                    result = await this.storageSet({recent: {rev: bm.recentRev + 1, data: bm.recent}, recentDelta: {rev: bm.recentDeltaRev + 1, data: {}}});
-                } catch(e) {
-                    this.error(`Ошибка соединения с сервером (${e.message}). Данные не сохранены и могут быть перезаписаны.`);
-                }
-
-                if (result.state == 'reject') {
-
-                    await this.loadRecent(true, false);
-
-                    this.warning(`Последние изменения отменены. Данные синхронизированы с сервером.`);
-                    if (!recurse) {
-                        this.savingRecent = false;
-                        this.recentDelta[itemKey] = _.cloneDeep(bm.recent[itemKey]);
-                        this.saveRecent(itemKey, true);
-                        return;
-                    }
-                } else if (result.state == 'success') {
-                    this.makeDeltaDiff = true;
-                    this.prevSavedItem = _.cloneDeep(bm.recent[itemKey]);
-
-                    this.recentDelta = {};
-                    await bm.setRecentRev(bm.recentRev + 1);
-                    await bm.setRecentDeltaRev(bm.recentDeltaRev + 1);
-                }
-            } else {//сохраняем только дифф
-                let result = {state: ''};
+            let result = {state: ''};
 
-                try {
-                    result = await this.storageSet({recentDelta: {rev: bm.recentDeltaRev + 1, data: this.recentDelta}});
-                } catch(e) {
-                    this.error(`Ошибка соединения с сервером (${e.message}). Данные не сохранены и могут быть перезаписаны.`);
-                }
+            try {
+                result = await this.storageSet(query);
+            } catch(e) {
+                this.error(`Ошибка соединения с сервером (${e.message}). Данные не сохранены и могут быть перезаписаны.`);
+            }
 
-                if (result.state == 'reject') {
+            if (result.state == 'reject') {
 
-                    await this.loadRecent(true, false);
+                await this.loadRecent(true, false);
 
-                    this.warning(`Последние изменения отменены. Данные синхронизированы с сервером.`);
-                    if (!recurse) {
-                        this.savingRecent = false;
-                        this.recentDelta[itemKey] = _.cloneDeep(bm.recent[itemKey]);
-                        this.saveRecent(itemKey, true);
-                        return;
-                    }
-                } else if (result.state == 'success') {
-                    await bm.setRecentDeltaRev(bm.recentDeltaRev + 1);
+                this.warning(`Последние изменения отменены. Данные синхронизированы с сервером.`);
+                if (!recurse) {
+                    this.savingRecent = false;
+                    this.saveRecent(itemKey, true);
+                    return;
                 }
+            } else if (result.state == 'success') {
+                //this.prevSavedItem = _.cloneDeep(bm.recent[itemKey]);
+
+                if (needSaveRecent)
+                    await this.setCachedRecent(newRecent);
+                if (needSaveRecentPatch)
+                    await this.setCachedRecentPatch(newRecentPatch);
+                if (needSaveRecentMod)
+                    await this.setCachedRecentMod(newRecentMod);
             }
         } finally {
             this.savingRecent = false;

+ 0 - 13
client/components/Reader/share/bookManager.js

@@ -36,9 +36,6 @@ class BookManager {
             }
         }
 
-        this.recentRev = await bmRecentStore.getItem('recent-rev') || 0;
-        this.recentDeltaRev = await bmRecentStore.getItem('recent-delta-rev') || 0;
-
         this.recentChanged = true;
 
         this.loadStored();//no await
@@ -466,16 +463,6 @@ class BookManager {
         this.emit('recent-changed');
     }
 
-    async setRecentRev(value) {
-        await bmRecentStore.setItem('recent-rev', value);
-        this.recentRev = value;
-    }
-
-    async setRecentDeltaRev(value) {
-        await bmRecentStore.setItem('recent-delta-rev', value);
-        this.recentDeltaRev = value;
-    }
-
     addEventListener(listener) {
         if (this.eventListeners.indexOf(listener) < 0)
             this.eventListeners.push(listener);