Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1370bae4d6 | ||
|
|
01fbdf38fa | ||
|
|
be6b07a0cf | ||
|
|
1b057029c8 | ||
|
|
b6b567f20b | ||
|
|
c4c109fe0e | ||
|
|
4c8c921b03 | ||
|
|
69a2e5cda3 | ||
|
|
c2adf8d5b8 | ||
|
|
5c8d257923 | ||
|
|
55dae33e60 | ||
|
|
57d8e9061f | ||
|
|
4642679842 | ||
|
|
ba18743fab | ||
|
|
e739356733 | ||
|
|
cae4aed8d2 | ||
|
|
6c6a08d8e0 | ||
|
|
deafbae945 | ||
|
|
0b23c609f1 | ||
|
|
0359061321 | ||
|
|
bc7a5f6be4 | ||
|
|
be36f8f6e8 | ||
|
|
3b8d084c76 | ||
|
|
ce1cdca6a0 |
@@ -101,7 +101,7 @@
|
||||
</template>
|
||||
</q-input>
|
||||
|
||||
<q-btn :disabled="!bookUrl" color="green-7" no-caps size="14px" @click="submitUrl">
|
||||
<q-btn :disabled="!bookUrl" color="green-7" no-caps size="14px" @click="submitUrl()">
|
||||
Открыть
|
||||
<q-tooltip :delay="1500" anchor="bottom middle" content-style="font-size: 80%">
|
||||
Открыть в читалке
|
||||
@@ -312,6 +312,7 @@ class ExternalLibs {
|
||||
inpxUrl = '';
|
||||
|
||||
created() {
|
||||
this.commit = this.$store.commit;
|
||||
this.oldStartLink = '';
|
||||
this.justOpened = true;
|
||||
this.$root.addEventHook('key', this.keyHook);
|
||||
@@ -404,6 +405,8 @@ class ExternalLibs {
|
||||
this.ready = true;
|
||||
if (d.data)
|
||||
this.libs = _.cloneDeep(d.data);
|
||||
if (d.sets)
|
||||
this.updateSets(d.sets);
|
||||
} else if (d.type == 'notify') {
|
||||
this.$root.notify.success(d.data, '', {position: 'bottom-right'});
|
||||
}
|
||||
@@ -448,6 +451,11 @@ class ExternalLibs {
|
||||
}
|
||||
}
|
||||
|
||||
updateSets(sets) {
|
||||
if (sets.nightMode !== this.nightMode)
|
||||
this.commit('reader/nightModeToggle');
|
||||
}
|
||||
|
||||
commitLibs(libs) {
|
||||
this.sendMessage({type: 'libs', data: libs});
|
||||
}
|
||||
@@ -496,6 +504,10 @@ class ExternalLibs {
|
||||
return this.$store.state.config.mode;
|
||||
}
|
||||
|
||||
get nightMode() {
|
||||
return this.$store.state.reader.settings.nightMode;
|
||||
}
|
||||
|
||||
get header() {
|
||||
let result = [this.ready ? 'Сетевая библиотека' : 'Загрузка...'];
|
||||
if (this.ready && this.selectedLink) {
|
||||
|
||||
@@ -34,8 +34,8 @@ class LibsPage {
|
||||
if (!this.mode)
|
||||
return;
|
||||
|
||||
//TODO: убрать второе условие в 24г
|
||||
if (!this.libs || (this.mode === 'omnireader' && this.libs.mode !== this.mode)) {
|
||||
//TODO: убрать условие с mode в 24г
|
||||
if (!this.libs || !this.libs.groups || (this.mode === 'omnireader' && this.libs.mode !== this.mode)) {
|
||||
const defaults = rstore.getLibsDefaults(this.mode);
|
||||
this.commit('reader/setLibs', defaults);
|
||||
}
|
||||
@@ -119,8 +119,12 @@ class LibsPage {
|
||||
return this.$store.state.reader.libs;
|
||||
}
|
||||
|
||||
get nightMode() {
|
||||
return this.$store.state.reader.settings.nightMode;
|
||||
}
|
||||
|
||||
sendLibs() {
|
||||
this.sendMessage({type: 'libs', data: _.cloneDeep(this.libs)});
|
||||
this.sendMessage({type: 'libs', data: _.cloneDeep(this.libs), sets: {nightMode: this.nightMode}});
|
||||
}
|
||||
|
||||
close() {
|
||||
|
||||
@@ -393,6 +393,9 @@ class Reader {
|
||||
this.recentItemKeys = [];
|
||||
//сохранение в удаленном хранилище
|
||||
await this.$refs.serverStorage.saveRecent(itemKeys);
|
||||
|
||||
//periodicTasks
|
||||
this.periodicTasks();//no await
|
||||
} catch (e) {
|
||||
if (!this.offlineModeActive)
|
||||
this.$root.notify.error(e.message);
|
||||
@@ -442,26 +445,15 @@ class Reader {
|
||||
this.$refs.recentBooksPage.init();
|
||||
})();
|
||||
|
||||
//проверки обновлений читалки
|
||||
//единственный запуск periodicTasks при инициализации
|
||||
//дальнейшие запуски periodicTasks выполняются из debouncedSaveRecent
|
||||
//т.е. только по действию пользователя
|
||||
(async() => {
|
||||
await utils.sleep(15*1000);
|
||||
this.isFirstNeedUpdateNotify = true;
|
||||
//вечный цикл, запрашиваем периодически конфиг для проверки выхода новой версии читалки
|
||||
while (1) {// eslint-disable-line no-constant-condition
|
||||
await this.checkNewVersionAvailable();
|
||||
await utils.sleep(60*60*1000); //каждый час
|
||||
}
|
||||
//дальше хода нет
|
||||
})();
|
||||
|
||||
//проверки обновлений книг
|
||||
(async() => {
|
||||
await utils.sleep(15*1000); //подождем неск. секунд перед первым запросом
|
||||
//вечный цикл, запрашиваем периодически обновления
|
||||
while (1) {// eslint-disable-line no-constant-condition
|
||||
await this.checkBuc();
|
||||
await utils.sleep(70*60*1000); //каждые 70 минут
|
||||
}
|
||||
//дальше хода нет
|
||||
this.allowPeriodicTasks = true;
|
||||
this.periodicTasks();//no await
|
||||
})();
|
||||
}
|
||||
|
||||
@@ -560,26 +552,56 @@ class Reader {
|
||||
}
|
||||
}
|
||||
|
||||
async checkNewVersionAvailable() {
|
||||
if (!this.checkingNewVersion && this.showNeedUpdateNotify) {
|
||||
this.checkingNewVersion = true;
|
||||
try {
|
||||
await utils.sleep(15*1000); //подождем 15 секунд, чтобы прогрузился ServiceWorker при выходе новой версии
|
||||
const config = await miscApi.loadConfig();
|
||||
this.commit('config/setConfig', config);
|
||||
async periodicTasks() {
|
||||
if (!this.allowPeriodicTasks || this.doingPeriodicTasks)
|
||||
return;
|
||||
|
||||
let againMes = '';
|
||||
if (this.isFirstNeedUpdateNotify) {
|
||||
againMes = ' еще один раз';
|
||||
this.doingPeriodicTasks = true;
|
||||
try {
|
||||
if (!this.taskList) {
|
||||
const taskArr = [
|
||||
[this.checkNewVersionAvailable, 60], //проверки обновлений читалки, каждый час
|
||||
[this.checkBuc, 70], //проверки обновлений книг, каждые 70 минут
|
||||
];
|
||||
|
||||
this.taskList = [];
|
||||
for (const task of taskArr) {
|
||||
const [method, period] = task;
|
||||
this.taskList.push({method, period, lastRunTime: 0});
|
||||
}
|
||||
}
|
||||
|
||||
for (const task of this.taskList) {
|
||||
if (Date.now() - task.lastRunTime >= task.period*60*1000) {
|
||||
try {
|
||||
//console.log('task run', task.method.name);
|
||||
await task.method();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
task.lastRunTime = Date.now();
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
} finally {
|
||||
this.doingPeriodicTasks = false;
|
||||
}
|
||||
}
|
||||
|
||||
async checkNewVersionAvailable() {
|
||||
if (this.showNeedUpdateNotify) {
|
||||
const config = await miscApi.loadConfig();
|
||||
this.commit('config/setConfig', config);
|
||||
|
||||
let againMes = '';
|
||||
if (this.isFirstNeedUpdateNotify) {
|
||||
againMes = ' еще один раз';
|
||||
}
|
||||
|
||||
if (this.version != this.clientVersion)
|
||||
this.$root.notify.info(`Вышла новая версия (v${this.version}) читалки.<br>Пожалуйста, обновите страницу${againMes}.`, 'Обновление');
|
||||
|
||||
if (this.version != this.clientVersion)
|
||||
this.$root.notify.info(`Вышла новая версия (v${this.version}) читалки.<br>Пожалуйста, обновите страницу${againMes}.`, 'Обновление');
|
||||
} catch(e) {
|
||||
console.error(e);
|
||||
} finally {
|
||||
this.checkingNewVersion = false;
|
||||
}
|
||||
this.isFirstNeedUpdateNotify = false;
|
||||
}
|
||||
}
|
||||
@@ -588,82 +610,78 @@ class Reader {
|
||||
if (!this.bothBucEnabled)
|
||||
return;
|
||||
|
||||
try {
|
||||
const sorted = bookManager.getSortedRecent();
|
||||
const sorted = bookManager.getSortedRecent();
|
||||
|
||||
//выберем все кандидиаты на обновление
|
||||
const updateUrls = new Set();
|
||||
for (const book of sorted) {
|
||||
if (!book.deleted && book.checkBuc && book.url && book.url.indexOf('disk://') !== 0)
|
||||
updateUrls.add(book.url);
|
||||
//выберем все кандидиаты на обновление
|
||||
const updateUrls = new Set();
|
||||
for (const book of sorted) {
|
||||
if (!book.deleted && book.checkBuc && book.url && book.url.indexOf('disk://') !== 0)
|
||||
updateUrls.add(book.url);
|
||||
}
|
||||
|
||||
//теперь по кусочкам запросим сервер
|
||||
const arr = Array.from(updateUrls);
|
||||
const bucSize = {};
|
||||
const chunkSize = 100;
|
||||
for (let i = 0; i < arr.length; i += chunkSize) {
|
||||
const chunk = arr.slice(i, i + chunkSize);
|
||||
|
||||
const data = await readerApi.checkBuc(chunk);
|
||||
|
||||
for (const item of data) {
|
||||
bucSize[item.id] = item.size;
|
||||
}
|
||||
|
||||
//теперь по кусочкам запросим сервер
|
||||
const arr = Array.from(updateUrls);
|
||||
const bucSize = {};
|
||||
const chunkSize = 100;
|
||||
for (let i = 0; i < arr.length; i += chunkSize) {
|
||||
const chunk = arr.slice(i, i + chunkSize);
|
||||
await utils.sleep(1000);//чтобы не ддосить сервер
|
||||
}
|
||||
|
||||
const data = await readerApi.checkBuc(chunk);
|
||||
|
||||
for (const item of data) {
|
||||
bucSize[item.id] = item.size;
|
||||
}
|
||||
|
||||
await utils.sleep(1000);//чтобы не ддосить сервер
|
||||
const checkSetTime = {};
|
||||
//проставим новые размеры у книг
|
||||
for (const book of sorted) {
|
||||
if (book.deleted)
|
||||
continue;
|
||||
|
||||
//размер 0 считаем отсутствующим
|
||||
if (book.url && bucSize[book.url] && bucSize[book.url] !== book.bucSize) {
|
||||
book.bucSize = bucSize[book.url];
|
||||
await bookManager.recentSetItem(book);
|
||||
}
|
||||
|
||||
const checkSetTime = {};
|
||||
//проставим новые размеры у книг
|
||||
for (const book of sorted) {
|
||||
if (book.deleted)
|
||||
continue;
|
||||
|
||||
//размер 0 считаем отсутствующим
|
||||
if (book.url && bucSize[book.url] && bucSize[book.url] !== book.bucSize) {
|
||||
book.bucSize = bucSize[book.url];
|
||||
await bookManager.recentSetItem(book);
|
||||
}
|
||||
//подготовка к следующему шагу, ищем книгу по url с максимальной датой установки checkBucTime/loadTime
|
||||
//от этой даты будем потом отсчитывать bucCancelDays
|
||||
if (updateUrls.has(book.url)) {
|
||||
let rec = checkSetTime[book.url] || {time: 0, loadTime: 0};
|
||||
|
||||
//подготовка к следующему шагу, ищем книгу по url с максимальной датой установки checkBucTime/loadTime
|
||||
//от этой даты будем потом отсчитывать bucCancelDays
|
||||
if (updateUrls.has(book.url)) {
|
||||
let rec = checkSetTime[book.url] || {time: 0, loadTime: 0};
|
||||
const time = (book.checkBucTime ? book.checkBucTime : (rec.loadTime || 0));
|
||||
if (time > rec.time || (time == rec.time && (book.loadTime > rec.loadTime)))
|
||||
rec = {time, loadTime: book.loadTime, key: book.key};
|
||||
|
||||
const time = (book.checkBucTime ? book.checkBucTime : (rec.loadTime || 0));
|
||||
if (time > rec.time || (time == rec.time && (book.loadTime > rec.loadTime)))
|
||||
rec = {time, loadTime: book.loadTime, key: book.key};
|
||||
|
||||
checkSetTime[book.url] = rec;
|
||||
}
|
||||
checkSetTime[book.url] = rec;
|
||||
}
|
||||
}
|
||||
|
||||
//bucCancelEnabled и bucCancelDays
|
||||
//снимем флаг checkBuc у необновлявшихся bucCancelDays
|
||||
if (this.bucCancelEnabled) {
|
||||
for (const rec of Object.values(checkSetTime)) {
|
||||
if (rec.time && Date.now() - rec.time > this.bucCancelDays*24*3600*1000) {
|
||||
const book = await bookManager.getRecentBook({key: rec.key});
|
||||
const needBookUpdate =
|
||||
book.checkBuc
|
||||
&& book.bucSize
|
||||
&& utils.hasProp(book, 'downloadSize')
|
||||
&& book.bucSize !== book.downloadSize
|
||||
&& (book.bucSize - book.downloadSize >= this.bucSizeDiff)
|
||||
;
|
||||
//bucCancelEnabled и bucCancelDays
|
||||
//снимем флаг checkBuc у необновлявшихся bucCancelDays
|
||||
if (this.bucCancelEnabled) {
|
||||
for (const rec of Object.values(checkSetTime)) {
|
||||
if (rec.time && Date.now() - rec.time > this.bucCancelDays*24*3600*1000) {
|
||||
const book = await bookManager.getRecentBook({key: rec.key});
|
||||
const needBookUpdate =
|
||||
book.checkBuc
|
||||
&& book.bucSize
|
||||
&& utils.hasProp(book, 'downloadSize')
|
||||
&& book.bucSize !== book.downloadSize
|
||||
&& (book.bucSize - book.downloadSize >= this.bucSizeDiff)
|
||||
;
|
||||
|
||||
if (book && !needBookUpdate) {
|
||||
await bookManager.setCheckBuc(book, undefined);//!!!
|
||||
}
|
||||
if (book && !needBookUpdate) {
|
||||
await bookManager.setCheckBuc(book, undefined);//!!!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await this.$refs.recentBooksPage.updateTableData();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
await this.$refs.recentBooksPage.updateTableData();
|
||||
}
|
||||
|
||||
updateCountChanged(event) {
|
||||
@@ -1409,8 +1427,6 @@ class Reader {
|
||||
if (!this.showHelpOnErrorIfNeeded(url)) {
|
||||
this.$root.stdDialog.alert(e.message, 'Ошибка', {color: 'negative'});
|
||||
}
|
||||
} finally {
|
||||
this.checkNewVersionAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,10 +22,12 @@ const ssCacheStore = localForage.createInstance({
|
||||
const componentOptions = {
|
||||
watch: {
|
||||
serverSyncEnabled: function() {
|
||||
this.serverSyncEnabledChanged();
|
||||
if (this.inited)
|
||||
this.serverSyncEnabledChanged();
|
||||
},
|
||||
serverStorageKey: function() {
|
||||
this.serverStorageKeyChanged(true);
|
||||
if (this.inited)
|
||||
this.serverStorageKeyChanged(true);
|
||||
},
|
||||
settings: function() {
|
||||
this.debouncedSaveSettings();
|
||||
@@ -85,6 +87,13 @@ class ServerStorage {
|
||||
if (!this.cachedRecentMod)
|
||||
await this.cleanCachedRecent('cachedRecentMod');
|
||||
|
||||
//подстраховка хранения ключа, восстановим из IndexedDB при проблемах в localStorage
|
||||
if (!this.serverStorageKey) {
|
||||
const key = await ssCacheStore.getItem('storageKey');
|
||||
if (key)
|
||||
this.commit('reader/setServerStorageKey', key);
|
||||
}
|
||||
|
||||
if (!this.serverStorageKey) {
|
||||
//генерируем новый ключ
|
||||
await this.generateNewServerStorageKey();
|
||||
@@ -123,6 +132,7 @@ class ServerStorage {
|
||||
async generateNewServerStorageKey() {
|
||||
const key = utils.toBase58(utils.randomArray(32));
|
||||
this.commit('reader/setServerStorageKey', key);
|
||||
//дождемся serverStorageKeyChanged, событие по watch не работает при this.inited == false
|
||||
await this.serverStorageKeyChanged(true);
|
||||
}
|
||||
|
||||
@@ -141,6 +151,10 @@ class ServerStorage {
|
||||
async serverStorageKeyChanged(force) {
|
||||
if (this.prevServerStorageKey != this.serverStorageKey) {
|
||||
this.prevServerStorageKey = this.serverStorageKey;
|
||||
|
||||
//сохраним ключ также в IndexedDB, чтобы была возможность восстановить при проблемах с localStorage
|
||||
await ssCacheStore.setItem('storageKey', this.serverStorageKey);
|
||||
|
||||
this.hashedStorageKey = utils.toBase58(cryptoUtils.sha256(this.serverStorageKey));
|
||||
this.keyInited = true;
|
||||
|
||||
|
||||
@@ -438,61 +438,63 @@ export default class BookParser {
|
||||
};
|
||||
|
||||
const onEndNode = (elemName) => {// eslint-disable-line no-unused-vars
|
||||
if (tag == elemName) {
|
||||
if (tag == 'binary') {
|
||||
binaryId = '';
|
||||
}
|
||||
|
||||
if (path.indexOf('/fictionbook/body') == 0) {
|
||||
if (tag == 'title') {
|
||||
isFirstTitlePara = false;
|
||||
bold = false;
|
||||
center = false;
|
||||
inTitle = false;
|
||||
}
|
||||
tag = elemName;
|
||||
|
||||
if (tag == 'section') {
|
||||
sectionLevel--;
|
||||
}
|
||||
|
||||
if (tag == 'emphasis' || tag == 'strong' || tag == 'sup' || tag == 'sub') {
|
||||
growParagraph(`</${tag}>`, 0);
|
||||
}
|
||||
|
||||
if (tag == 'p') {
|
||||
inPara = false;
|
||||
}
|
||||
|
||||
if (tag == 'subtitle') {
|
||||
isFirstTitlePara = false;
|
||||
bold = false;
|
||||
center = false;
|
||||
inSubtitle = false;
|
||||
}
|
||||
|
||||
if (tag == 'epigraph' || tag == 'annotation') {
|
||||
italic = false;
|
||||
space -= 1;
|
||||
newParagraph();
|
||||
}
|
||||
|
||||
if (tag == 'stanza') {
|
||||
newParagraph();
|
||||
}
|
||||
|
||||
if (tag == 'text-author') {
|
||||
bold = false;
|
||||
space -= 1;
|
||||
}
|
||||
if (tag == 'binary') {
|
||||
binaryId = '';
|
||||
}
|
||||
|
||||
if (path.indexOf('/fictionbook/body') == 0) {
|
||||
if (tag == 'title') {
|
||||
isFirstTitlePara = false;
|
||||
bold = false;
|
||||
center = false;
|
||||
inTitle = false;
|
||||
}
|
||||
|
||||
path = path.substr(0, path.length - tag.length - 1);
|
||||
let i = path.lastIndexOf('/');
|
||||
if (i >= 0) {
|
||||
tag = path.substr(i + 1);
|
||||
} else {
|
||||
if (tag == 'section') {
|
||||
sectionLevel--;
|
||||
}
|
||||
|
||||
if (tag == 'emphasis' || tag == 'strong' || tag == 'sup' || tag == 'sub') {
|
||||
growParagraph(`</${tag}>`, 0);
|
||||
}
|
||||
|
||||
if (tag == 'p') {
|
||||
inPara = false;
|
||||
}
|
||||
|
||||
if (tag == 'subtitle') {
|
||||
isFirstTitlePara = false;
|
||||
bold = false;
|
||||
center = false;
|
||||
inSubtitle = false;
|
||||
}
|
||||
|
||||
if (tag == 'epigraph' || tag == 'annotation') {
|
||||
italic = false;
|
||||
space -= 1;
|
||||
newParagraph();
|
||||
}
|
||||
|
||||
if (tag == 'stanza') {
|
||||
newParagraph();
|
||||
}
|
||||
|
||||
if (tag == 'text-author') {
|
||||
bold = false;
|
||||
space -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
let i = path.lastIndexOf(tag);
|
||||
if (i >= 0) {
|
||||
path = path.substring(0, i - 1);
|
||||
i = path.lastIndexOf('/');
|
||||
if (i >= 0)
|
||||
tag = path.substring(i + 1);
|
||||
else
|
||||
tag = path;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,32 @@
|
||||
export const versionHistory = [
|
||||
{
|
||||
version: '1.1.0',
|
||||
version: '1.1.3',
|
||||
releaseDate: '2023-02-06',
|
||||
showUntil: '2023-02-05',
|
||||
content:
|
||||
`
|
||||
<ul>
|
||||
<li>исправление багов</li>
|
||||
</ul>
|
||||
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
version: '1.1.2',
|
||||
releaseDate: '2023-01-22',
|
||||
showUntil: '2023-01-21',
|
||||
content:
|
||||
`
|
||||
<ul>
|
||||
<li>исправление багов</li>
|
||||
</ul>
|
||||
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
version: '1.1.1',
|
||||
releaseDate: '2023-01-11',
|
||||
showUntil: '2023-01-15',
|
||||
content:
|
||||
|
||||
@@ -325,7 +325,7 @@ const state = {
|
||||
currentProfile: '',
|
||||
settings: _.cloneDeep(settingDefaults),
|
||||
settingsRev: {},
|
||||
libs: false,
|
||||
libs: {},
|
||||
libsRev: 0,
|
||||
};
|
||||
|
||||
|
||||
18
package-lock.json
generated
18
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "liberama",
|
||||
"version": "1.1.0",
|
||||
"version": "1.1.3",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "liberama",
|
||||
"version": "1.1.0",
|
||||
"version": "1.1.3",
|
||||
"hasInstallScript": true,
|
||||
"license": "CC0-1.0",
|
||||
"dependencies": {
|
||||
@@ -22,7 +22,7 @@
|
||||
"fs-extra": "^10.1.0",
|
||||
"he": "^1.2.0",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"jembadb": "^5.1.5",
|
||||
"jembadb": "^5.1.7",
|
||||
"localforage": "^1.10.0",
|
||||
"lodash": "^4.17.21",
|
||||
"minimist": "^1.2.7",
|
||||
@@ -5989,9 +5989,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/jembadb": {
|
||||
"version": "5.1.5",
|
||||
"resolved": "https://registry.npmjs.org/jembadb/-/jembadb-5.1.5.tgz",
|
||||
"integrity": "sha512-Vb+TkTg3JVXLPTG5BiqboZjJ2wvZRONnLd2+qU4gTuaqt2JSniigbniKSl3kACAEFfuRXEjfs9dLlKWjBX2Aiw==",
|
||||
"version": "5.1.7",
|
||||
"resolved": "https://registry.npmjs.org/jembadb/-/jembadb-5.1.7.tgz",
|
||||
"integrity": "sha512-TNZjiKQ7Zfh89Q1x25PKKtsbkxiC5uOnx953dxJEP6RqfcdR6uVpr4cf+kmyq6IQ1GhwhXTELnoTIdvLWrpEvw==",
|
||||
"engines": {
|
||||
"node": ">=16.16.0"
|
||||
}
|
||||
@@ -15154,9 +15154,9 @@
|
||||
}
|
||||
},
|
||||
"jembadb": {
|
||||
"version": "5.1.5",
|
||||
"resolved": "https://registry.npmjs.org/jembadb/-/jembadb-5.1.5.tgz",
|
||||
"integrity": "sha512-Vb+TkTg3JVXLPTG5BiqboZjJ2wvZRONnLd2+qU4gTuaqt2JSniigbniKSl3kACAEFfuRXEjfs9dLlKWjBX2Aiw=="
|
||||
"version": "5.1.7",
|
||||
"resolved": "https://registry.npmjs.org/jembadb/-/jembadb-5.1.7.tgz",
|
||||
"integrity": "sha512-TNZjiKQ7Zfh89Q1x25PKKtsbkxiC5uOnx953dxJEP6RqfcdR6uVpr4cf+kmyq6IQ1GhwhXTELnoTIdvLWrpEvw=="
|
||||
},
|
||||
"jest-util": {
|
||||
"version": "29.3.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "liberama",
|
||||
"version": "1.1.0",
|
||||
"version": "1.1.3",
|
||||
"author": "Book Pauk <bookpauk@gmail.com>",
|
||||
"license": "CC0-1.0",
|
||||
"repository": "bookpauk/liberama",
|
||||
@@ -65,7 +65,7 @@
|
||||
"fs-extra": "^10.1.0",
|
||||
"he": "^1.2.0",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"jembadb": "^5.1.5",
|
||||
"jembadb": "^5.1.7",
|
||||
"localforage": "^1.10.0",
|
||||
"lodash": "^4.17.21",
|
||||
"minimist": "^1.2.7",
|
||||
|
||||
@@ -24,6 +24,7 @@ class JembaReaderStorage {
|
||||
|
||||
getCache(id) {
|
||||
const obj = this.cacheMap.get(id);
|
||||
//обновляем время доступа и при чтении тоже
|
||||
if (obj)
|
||||
obj.time = Date.now();
|
||||
return obj;
|
||||
@@ -118,6 +119,7 @@ class JembaReaderStorage {
|
||||
//identity необходимо для работы при нестабильной связи,
|
||||
//одному и тому же клиенту разрешается перезаписывать данные при расхождении на 0 или 1 ревизию
|
||||
const obj = this.getCache(id) || {};
|
||||
const oldIdentity = obj.identity;
|
||||
const sameClient = (identity && obj.identity === identity);
|
||||
if (identity && obj.identity !== identity) {
|
||||
obj.identity = identity;
|
||||
@@ -126,8 +128,12 @@ class JembaReaderStorage {
|
||||
|
||||
const revDiff = items[id].rev - check.items[id].rev;
|
||||
const allowUpdate = force || revDiff === 1 || (sameClient && (revDiff === 0 || revDiff === 1));
|
||||
if (!allowUpdate)
|
||||
|
||||
if (!allowUpdate) {
|
||||
log(LM_ERR, `JembaReaderStorage-Reject: revDiff: ${revDiff}, sameClient: ${sameClient}, oldIdentity: ${oldIdentity}, identity: ${identity}`);
|
||||
|
||||
return {state: 'reject', items: check.items};
|
||||
}
|
||||
}
|
||||
|
||||
const db = this.db;
|
||||
|
||||
Reference in New Issue
Block a user