Рефакторинг, упрощение, начало переделки ServerStorage

This commit is contained in:
Book Pauk
2019-08-22 15:37:15 +07:00
parent eae2c2b102
commit a2c393b06b
3 changed files with 123 additions and 198 deletions

View File

@@ -18,46 +18,30 @@ const bmRecentStore = localForage.createInstance({
name: 'bmRecentStore'
});
const bmCacheStore = localForage.createInstance({
name: 'bmCacheStore'
});
class BookManager {
async init(settings) {
this.loaded = false;
this.settings = settings;
this.eventListeners = [];
this.books = {};
this.recent = {};
//bmCacheStore нужен только для ускорения загрузки читалки
this.booksCached = await bmCacheStore.getItem('books');
if (!this.booksCached)
this.booksCached = {};
this.recent = await bmCacheStore.getItem('recent');
this.recentLast = await bmCacheStore.getItem('recent-last');
this.recentLast = await bmRecentStore.getItem('recent-last');
if (this.recentLast)
this.recent[this.recentLast.key] = this.recentLast;
this.recentRev = await bmRecentStore.getItem('recent-rev') || 0;
this.recentLastRev = await bmRecentStore.getItem('recent-last-rev') || 0;
this.recentLastDiffRev = await bmRecentStore.getItem('recent-last-diff-rev') || 0;
this.books = Object.assign({}, this.booksCached);
this.recentChanged2 = true;
this.recentChanged = true;
if (!this.books || !this.recent) {
this.books = {};
this.recent = {};
await this.loadMeta(true);
} else {
this.loadMeta(false);
}
this.loadStored();//no await
}
//долгая загрузка из хранилища,
//хранение в отдельных записях дает относительно
//нормальное поведение при нескольких вкладках с читалкой в браузере
async loadMeta(immediate) {
if (!immediate)
await utils.sleep(2000);
//Долгая асинхронная загрузка из хранилища.
//Хранение в отдельных записях дает относительно
//нормальное поведение при нескольких вкладках с читалкой в браузере.
async loadStored() {
//даем время для загрузки последней читаемой книги, чтобы не блокировать приложение
await utils.sleep(2000);
let len = await bmMetaStore.length();
for (let i = 0; i < len; i++) {
@@ -68,6 +52,7 @@ class BookManager {
let meta = await bmMetaStore.getItem(key);
if (_.isObject(meta)) {
//уже может быть распарсена книга
const oldBook = this.books[meta.key];
this.books[meta.key] = meta;
@@ -80,22 +65,19 @@ class BookManager {
}
}
//"ленивая" загрузка
(async() => {
let key = null;
len = await bmRecentStore.length();
for (let i = 0; i < len; i++) {
key = await bmRecentStore.key(i);
if (key) {
let r = await bmRecentStore.getItem(key);
if (_.isObject(r) && r.key) {
this.recent[r.key] = r;
}
} else {
await bmRecentStore.removeItem(key);
let key = null;
len = await bmRecentStore.length();
for (let i = 0; i < len; i++) {
key = await bmRecentStore.key(i);
if (key) {
let r = await bmRecentStore.getItem(key);
if (_.isObject(r) && r.key) {
this.recent[r.key] = r;
}
} else {
await bmRecentStore.removeItem(key);
}
})();
}
//размножение для дебага
/*if (key) {
@@ -106,17 +88,10 @@ class BookManager {
}*/
await this.cleanBooks();
await this.cleanRecentBooks();
//очистка позже
//await this.cleanRecentBooks();
this.booksCached = {};
for (const key in this.books) {
this.booksCached[key] = this.metaOnly(this.books[key]);
}
await bmCacheStore.setItem('books', this.booksCached);
await bmCacheStore.setItem('recent', this.recent);
this.emit('load-meta-finish');
this.loaded = true;
this.emit('load-stored-finish');
}
async cleanBooks() {
@@ -136,7 +111,7 @@ class BookManager {
}
if (size > maxDataSize && toDel) {
await this._delBook(toDel);
await this.delBook(toDel);
} else {
break;
}
@@ -211,9 +186,7 @@ class BookManager {
return inflator.result;
}
async addBook(newBook, callback) {
if (!this.books)
await this.init();
async addBook(newBook, callback) {
let meta = {url: newBook.url, path: newBook.path};
meta.key = this.keyFromUrl(meta.url);
meta.addTime = Date.now();
@@ -233,43 +206,53 @@ class BookManager {
let data = newBook.data;
if (result.dataCompressed) {
//data = utils.pako.deflate(data, {level: 9});
//data = utils.pako.deflate(data, {level: 5});
data = await this.deflateWithProgress(data, cb2);
result.dataCompressedLength = data.byteLength;
}
callback(95);
this.books[meta.key] = result;
this.booksCached[meta.key] = this.metaOnly(result);
await bmMetaStore.setItem(`bmMeta-${meta.key}`, this.metaOnly(result));
await bmDataStore.setItem(`bmData-${meta.key}`, data);
await bmCacheStore.setItem('books', this.booksCached);
callback(100);
return result;
}
hasBookParsed(meta) {
async hasBookParsed(meta) {
if (!this.books)
return false;
if (!meta.url)
return false;
if (!meta.key)
meta.key = this.keyFromUrl(meta.url);
let book = this.books[meta.key];
if (!book && !this.loaded) {
book = await bmDataStore.getItem(`bmMeta-${meta.key}`);
if (book)
this.books[meta.key] = book;
}
return !!(book && book.parsed);
}
async getBook(meta, callback) {
if (!this.books)
await this.init();
let result = undefined;
if (!meta.key)
meta.key = this.keyFromUrl(meta.url);
result = this.books[meta.key];
if (!result) {
result = await bmDataStore.getItem(`bmMeta-${meta.key}`);
if (result)
this.books[meta.key] = result;
}
if (result && !result.parsed) {
let data = await bmDataStore.getItem(`bmData-${meta.key}`);
callback(5);
@@ -303,27 +286,14 @@ class BookManager {
return result;
}
async _delBook(meta) {
async delBook(meta) {
await bmMetaStore.removeItem(`bmMeta-${meta.key}`);
await bmDataStore.removeItem(`bmData-${meta.key}`);
delete this.books[meta.key];
delete this.booksCached[meta.key];
}
async delBook(meta) {
if (!this.books)
await this.init();
await this._delBook(meta);
await bmCacheStore.setItem('books', this.booksCached);
}
async parseBook(meta, data, callback) {
if (!this.books)
await this.init();
const parsed = new BookParser(this.settings);
const parsedMeta = await parsed.parse(data, callback);
@@ -347,9 +317,8 @@ class BookManager {
return utils.stringToHex(url);
}
//-- recent --------------------------------------------------------------
async setRecentBook(value) {
if (!this.recent)
await this.init();
const result = this.metaOnly(value);
result.touchTime = Date.now();
result.deleted = 0;
@@ -366,66 +335,51 @@ class BookManager {
await bmRecentStore.setItem(result.key, result);
//кэшируем, аккуратно
let saveRecent = false;
if (!(this.recentLast && this.recentLast.key == result.key)) {
await bmCacheStore.setItem('recent', this.recent);
saveRecent = true;
}
this.recentLast = result;
await bmCacheStore.setItem('recent-last', this.recentLast);
await bmRecentStore.setItem('recent-last', this.recentLast);
this.mostRecentCached = result;
this.recentChanged2 = true;
if (saveRecent)
this.emit('save-recent');
this.emit('recent-changed');
this.recentChanged = true;
return result;
}
async getRecentBook(value) {
if (!this.recent)
await this.init();
return this.recent[value.key];
let result = this.recent[value.key];
if (!result) {
result = await bmRecentStore.getItem(value.key);
this.recent[value.key] = result;
}
return result;
}
async delRecentBook(value) {
if (!this.recent)
await this.init();
this.recent[value.key].deleted = 1;
await bmRecentStore.setItem(value.key, this.recent[value.key]);
await bmCacheStore.setItem('recent', this.recent);
this.mostRecentCached = null;
this.recentChanged2 = true;
this.recentLast = null;
await bmRecentStore.setItem('recent-last', this.recentLast);
this.emit('save-recent');
this.recentChanged = true;
}
async cleanRecentBooks() {
if (!this.recent)
await this.init();
const sorted = this.getSortedRecent();
let isDel = false;
for (let i = 1000; i < sorted.length; i++) {
await bmRecentStore.removeItem(sorted[i].key);
delete this.recent[sorted[i].key];
await bmRecentStore.removeItem(sorted[i].key);
isDel = true;
}
this.sortedRecentCached = null;
await bmCacheStore.setItem('recent', this.recent);
return isDel;
}
mostRecentBook() {
if (this.mostRecentCached) {
return this.mostRecentCached;
if (this.recentLast) {
return this.recentLast;
}
let max = 0;
@@ -437,12 +391,14 @@ class BookManager {
result = book;
}
}
this.mostRecentCached = result;
this.recentLast = result;
bmRecentStore.setItem('recent-last', this.recentLast);//no await
return result;
}
getSortedRecent() {
if (!this.recentChanged2 && this.sortedRecentCached) {
if (!this.recentChanged && this.sortedRecentCached) {
return this.sortedRecentCached;
}
@@ -451,78 +407,10 @@ class BookManager {
result.sort((a, b) => b.touchTime - a.touchTime);
this.sortedRecentCached = result;
this.recentChanged2 = false;
this.recentChanged = false;
return result;
}
async setRecent(value) {
const mergedRecent = _.cloneDeep(this.recent);
Object.assign(mergedRecent, value);
const newRecent = {};
//"ленивое" обновление хранилища
(async() => {
for (const rec of Object.values(mergedRecent)) {
if (rec.key) {
await bmRecentStore.setItem(rec.key, rec);
await utils.sleep(1);
}
}
})();
for (const rec of Object.values(mergedRecent)) {
if (rec.key) {
newRecent[rec.key] = rec;
}
}
this.recent = newRecent;
await bmCacheStore.setItem('recent', this.recent);
this.recentLast = null;
await bmCacheStore.setItem('recent-last', this.recentLast);
this.mostRecentCached = null;
this.emit('recent-changed');
}
async setRecentRev(value) {
await bmRecentStore.setItem('recent-rev', value);
this.recentRev = value;
}
async setRecentLast(value) {
if (!value.key)
value = null;
this.recentLast = value;
await bmCacheStore.setItem('recent-last', this.recentLast);
if (value && value.key) {
//гарантия переключения книги
const mostRecent = this.mostRecentBook();
if (mostRecent)
this.recent[mostRecent.key].touchTime = value.touchTime - 1;
this.recent[value.key] = value;
await bmRecentStore.setItem(value.key, value);
await bmCacheStore.setItem('recent', this.recent);
}
this.mostRecentCached = null;
this.emit('recent-changed');
}
async setRecentLastRev(value) {
await bmRecentStore.setItem('recent-last-rev', value);
this.recentLastRev = value;
}
async setRecentLastDiffRev(value) {
await bmRecentStore.setItem('recent-last-diff-rev', value);
this.recentLastDiffRev = value;
}
addEventListener(listener) {
if (this.eventListeners.indexOf(listener) < 0)
this.eventListeners.push(listener);