Работа над списком книг в серии
This commit is contained in:
@@ -220,6 +220,16 @@ class Api {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getSeriesBookList(seriesId) {
|
||||||
|
const response = await this.request({action: 'get-series-book-list', seriesId});
|
||||||
|
|
||||||
|
if (response.error) {
|
||||||
|
throw new Error(response.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
async getGenreTree() {
|
async getGenreTree() {
|
||||||
const response = await this.request({action: 'get-genre-tree'});
|
const response = await this.request({action: 'get-genre-tree'});
|
||||||
|
|
||||||
|
|||||||
@@ -878,6 +878,29 @@ class Search {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async loadSeriesBooks(seriesId) {
|
||||||
|
try {
|
||||||
|
let result;
|
||||||
|
|
||||||
|
if (this.abCacheEnabled) {
|
||||||
|
const key = `series-${seriesId}-${this.inpxHash}`;
|
||||||
|
const data = await authorBooksStorage.getData(key);
|
||||||
|
if (data) {
|
||||||
|
result = JSON.parse(data);
|
||||||
|
} else {
|
||||||
|
result = await this.api.getBookList(seriesId);
|
||||||
|
await authorBooksStorage.setData(key, JSON.stringify(result));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = await this.api.getBookList(seriesId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return JSON.parse(result.books);
|
||||||
|
} catch (e) {
|
||||||
|
this.$root.stdDialog.alert(e.message, 'Ошибка');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
filterBooks(loadedBooks) {
|
filterBooks(loadedBooks) {
|
||||||
const s = this.search;
|
const s = this.search;
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ class WebSocketController {
|
|||||||
await this.search(req, ws); break;
|
await this.search(req, ws); break;
|
||||||
case 'get-book-list':
|
case 'get-book-list':
|
||||||
await this.getBookList(req, ws); break;
|
await this.getBookList(req, ws); break;
|
||||||
|
case 'get-series-book-list':
|
||||||
|
await this.getSeriesBookList(req, ws); break;
|
||||||
case 'get-genre-tree':
|
case 'get-genre-tree':
|
||||||
await this.getGenreTree(req, ws); break;
|
await this.getGenreTree(req, ws); break;
|
||||||
case 'get-book-link':
|
case 'get-book-link':
|
||||||
@@ -150,6 +152,15 @@ class WebSocketController {
|
|||||||
this.send(result, req, ws);
|
this.send(result, req, ws);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getSeriesBookList(req, ws) {
|
||||||
|
if (!utils.hasProp(req, 'seriesId'))
|
||||||
|
throw new Error(`seriesId is empty`);
|
||||||
|
|
||||||
|
const result = await this.webWorker.getSeriesBookList(req.seriesId);
|
||||||
|
|
||||||
|
this.send(result, req, ws);
|
||||||
|
}
|
||||||
|
|
||||||
async getGenreTree(req, ws) {
|
async getGenreTree(req, ws) {
|
||||||
const result = await this.webWorker.getGenreTree();
|
const result = await this.webWorker.getGenreTree();
|
||||||
|
|
||||||
|
|||||||
@@ -307,12 +307,12 @@ class DbCreator {
|
|||||||
callback({progress: 1});
|
callback({progress: 1});
|
||||||
|
|
||||||
//чистка памяти, ибо жрет как не в себя
|
//чистка памяти, ибо жрет как не в себя
|
||||||
await db.drop({table: 'book'});
|
await db.close({table: 'book'});
|
||||||
await db.freeMemory();
|
await db.freeMemory();
|
||||||
utils.freeMemory();
|
utils.freeMemory();
|
||||||
|
|
||||||
//парсинг 2, подготовка
|
//парсинг 2, подготовка
|
||||||
const parseField = (fieldValue, fieldMap, fieldArr, authorIds) => {
|
const parseField = (fieldValue, fieldMap, fieldArr, authorIds, bookId) => {
|
||||||
if (!fieldValue)
|
if (!fieldValue)
|
||||||
fieldValue = emptyFieldValue;
|
fieldValue = emptyFieldValue;
|
||||||
|
|
||||||
@@ -324,6 +324,8 @@ class DbCreator {
|
|||||||
fieldRec = fieldArr[fieldId];
|
fieldRec = fieldArr[fieldId];
|
||||||
} else {
|
} else {
|
||||||
fieldRec = {id: fieldArr.length, value, authorId: new Set()};
|
fieldRec = {id: fieldArr.length, value, authorId: new Set()};
|
||||||
|
if (bookId)
|
||||||
|
fieldRec.bookId = new Set();
|
||||||
fieldArr.push(fieldRec);
|
fieldArr.push(fieldRec);
|
||||||
fieldMap.set(value, fieldRec.id);
|
fieldMap.set(value, fieldRec.id);
|
||||||
}
|
}
|
||||||
@@ -331,6 +333,9 @@ class DbCreator {
|
|||||||
for (const id of authorIds) {
|
for (const id of authorIds) {
|
||||||
fieldRec.authorId.add(id);
|
fieldRec.authorId.add(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bookId)
|
||||||
|
fieldRec.bookId.add(bookId);
|
||||||
};
|
};
|
||||||
|
|
||||||
const parseBookRec = (rec) => {
|
const parseBookRec = (rec) => {
|
||||||
@@ -346,7 +351,7 @@ class DbCreator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//серии
|
//серии
|
||||||
parseField(rec.series, seriesMap, seriesArr, authorIds);
|
parseField(rec.series, seriesMap, seriesArr, authorIds, rec.id);
|
||||||
|
|
||||||
//названия
|
//названия
|
||||||
parseField(rec.title, titleMap, titleArr, authorIds);
|
parseField(rec.title, titleMap, titleArr, authorIds);
|
||||||
@@ -464,7 +469,7 @@ class DbCreator {
|
|||||||
//сохраним поисковые таблицы
|
//сохраним поисковые таблицы
|
||||||
const chunkSize = 10000;
|
const chunkSize = 10000;
|
||||||
|
|
||||||
const saveTable = async(table, arr, nullArr, authorIdToArray = true) => {
|
const saveTable = async(table, arr, nullArr, authorIdToArray = false, bookIdToArray = false) => {
|
||||||
|
|
||||||
arr.sort((a, b) => a.value.localeCompare(b.value));
|
arr.sort((a, b) => a.value.localeCompare(b.value));
|
||||||
|
|
||||||
@@ -482,6 +487,11 @@ class DbCreator {
|
|||||||
rec.authorId = Array.from(rec.authorId);
|
rec.authorId = Array.from(rec.authorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bookIdToArray) {
|
||||||
|
for (const rec of chunk)
|
||||||
|
rec.bookId = Array.from(rec.bookId);
|
||||||
|
}
|
||||||
|
|
||||||
await db.insert({table, rows: chunk});
|
await db.insert({table, rows: chunk});
|
||||||
|
|
||||||
if (i % 5 == 0) {
|
if (i % 5 == 0) {
|
||||||
@@ -500,23 +510,23 @@ class DbCreator {
|
|||||||
|
|
||||||
//author
|
//author
|
||||||
callback({job: 'author save', jobMessage: 'Сохранение индекса авторов', jobStep: 6, progress: 0});
|
callback({job: 'author save', jobMessage: 'Сохранение индекса авторов', jobStep: 6, progress: 0});
|
||||||
await saveTable('author', authorArr, () => {authorArr = null}, false);
|
await saveTable('author', authorArr, () => {authorArr = null});
|
||||||
|
|
||||||
//series
|
//series
|
||||||
callback({job: 'series save', jobMessage: 'Сохранение индекса серий', jobStep: 7, progress: 0});
|
callback({job: 'series save', jobMessage: 'Сохранение индекса серий', jobStep: 7, progress: 0});
|
||||||
await saveTable('series', seriesArr, () => {seriesArr = null});
|
await saveTable('series', seriesArr, () => {seriesArr = null}, true, true);
|
||||||
|
|
||||||
//title
|
//title
|
||||||
callback({job: 'title save', jobMessage: 'Сохранение индекса названий', jobStep: 8, progress: 0});
|
callback({job: 'title save', jobMessage: 'Сохранение индекса названий', jobStep: 8, progress: 0});
|
||||||
await saveTable('title', titleArr, () => {titleArr = null});
|
await saveTable('title', titleArr, () => {titleArr = null}, true);
|
||||||
|
|
||||||
//genre
|
//genre
|
||||||
callback({job: 'genre save', jobMessage: 'Сохранение индекса жанров', jobStep: 9, progress: 0});
|
callback({job: 'genre save', jobMessage: 'Сохранение индекса жанров', jobStep: 9, progress: 0});
|
||||||
await saveTable('genre', genreArr, () => {genreArr = null});
|
await saveTable('genre', genreArr, () => {genreArr = null}, true);
|
||||||
|
|
||||||
//lang
|
//lang
|
||||||
callback({job: 'lang save', jobMessage: 'Сохранение индекса языков', jobStep: 10, progress: 0});
|
callback({job: 'lang save', jobMessage: 'Сохранение индекса языков', jobStep: 10, progress: 0});
|
||||||
await saveTable('lang', langArr, () => {langArr = null});
|
await saveTable('lang', langArr, () => {langArr = null}, true);
|
||||||
|
|
||||||
//кэш-таблицы запросов
|
//кэш-таблицы запросов
|
||||||
await db.create({table: 'query_cache'});
|
await db.create({table: 'query_cache'});
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ class DbSearcher {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let author = '';
|
let author = '';
|
||||||
let books = [];
|
let books = '';
|
||||||
|
|
||||||
if (rows.length) {
|
if (rows.length) {
|
||||||
author = rows[0].author;
|
author = rows[0].author;
|
||||||
@@ -331,6 +331,75 @@ class DbSearcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async selectSeriesBookList(seriesId) {
|
||||||
|
const db = this.db;
|
||||||
|
|
||||||
|
//выборка серии по seriesId
|
||||||
|
const rows = await db.select({
|
||||||
|
table: 'series',
|
||||||
|
where: `@@id(${db.esc(seriesId)})`
|
||||||
|
});
|
||||||
|
|
||||||
|
let books = [];
|
||||||
|
|
||||||
|
if (rows.length) {
|
||||||
|
books = await db.select({
|
||||||
|
table: 'book',
|
||||||
|
where: `@@id(${db.esc(rows[0].bookId)})`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {books: JSON.stringify(books)};
|
||||||
|
}
|
||||||
|
|
||||||
|
async getSeriesBookList(seriesId) {
|
||||||
|
if (this.closed)
|
||||||
|
throw new Error('DbSearcher closed');
|
||||||
|
|
||||||
|
this.searchFlag++;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const db = this.db;
|
||||||
|
|
||||||
|
let result;
|
||||||
|
|
||||||
|
if (this.config.queryCacheEnabled) {
|
||||||
|
const key = `series_books-${seriesId}`;
|
||||||
|
const rows = await db.select({table: 'query_cache', where: `@@id(${db.esc(key)})`});
|
||||||
|
|
||||||
|
if (rows.length) {//нашли в кеше
|
||||||
|
await db.insert({
|
||||||
|
table: 'query_time',
|
||||||
|
replace: true,
|
||||||
|
rows: [{id: key, time: Date.now()}],
|
||||||
|
});
|
||||||
|
|
||||||
|
result = rows[0].value;
|
||||||
|
} else {//не нашли в кеше
|
||||||
|
result = await this.selectSeriesBookList(seriesId);
|
||||||
|
|
||||||
|
//кладем в кеш
|
||||||
|
await db.insert({
|
||||||
|
table: 'query_cache',
|
||||||
|
replace: true,
|
||||||
|
rows: [{id: key, value: result}],
|
||||||
|
});
|
||||||
|
await db.insert({
|
||||||
|
table: 'query_time',
|
||||||
|
replace: true,
|
||||||
|
rows: [{id: key, time: Date.now()}],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = await this.selectSeriesBookList(seriesId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} finally {
|
||||||
|
this.searchFlag--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async periodicCleanCache() {
|
async periodicCleanCache() {
|
||||||
this.timer = null;
|
this.timer = null;
|
||||||
const cleanInterval = this.config.cacheCleanInterval*60*1000;
|
const cleanInterval = this.config.cacheCleanInterval*60*1000;
|
||||||
|
|||||||
@@ -227,6 +227,12 @@ class WebWorker {
|
|||||||
return await this.dbSearcher.getBookList(authorId);
|
return await this.dbSearcher.getBookList(authorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getSeriesBookList(seriesId) {
|
||||||
|
this.checkMyState();
|
||||||
|
|
||||||
|
return await this.dbSearcher.getSeriesBookList(seriesId);
|
||||||
|
}
|
||||||
|
|
||||||
async getGenreTree() {
|
async getGenreTree() {
|
||||||
this.checkMyState();
|
this.checkMyState();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user