From be86a1535186e12a7ad8876d7dc5f88edd63e522 Mon Sep 17 00:00:00 2001 From: Book Pauk Date: Wed, 22 Jan 2020 21:37:28 +0700 Subject: [PATCH 1/8] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB?= =?UTF-8?q?=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B9=D0=BA=D1=83=20pro?= =?UTF-8?q?xy=5Fread=5Ftimeout?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/omnireader/omnireader | 1 + docs/omnireader/omnireader_http | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/omnireader/omnireader b/docs/omnireader/omnireader index dc4bba13..3e535374 100644 --- a/docs/omnireader/omnireader +++ b/docs/omnireader/omnireader @@ -8,6 +8,7 @@ server { server_name omnireader.ru; client_max_body_size 50m; + proxy_read_timeout 1h; gzip on; gzip_min_length 1024; diff --git a/docs/omnireader/omnireader_http b/docs/omnireader/omnireader_http index a5d84d83..768fce76 100644 --- a/docs/omnireader/omnireader_http +++ b/docs/omnireader/omnireader_http @@ -3,6 +3,7 @@ server { server_name omnireader.ru; client_max_body_size 50m; + proxy_read_timeout 1h; gzip on; gzip_min_length 1024; From 12e7a783b096210b932f50ee9f41f499249edf33 Mon Sep 17 00:00:00 2001 From: Book Pauk Date: Wed, 22 Jan 2020 22:06:12 +0700 Subject: [PATCH 2/8] =?UTF-8?q?=D0=9D=D0=B5=D0=B1=D0=BE=D0=BB=D1=8C=D1=88?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=B1=D0=BB=D0=BE=D0=BA=D0=B8=D1=80=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=BA=D0=BD=D0=BE=D0=BF=D0=BE=D0=BA=20?= =?UTF-8?q?=D0=BF=D0=B0=D0=BD=D0=B5=D0=BB=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/components/Reader/Reader.vue | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/client/components/Reader/Reader.vue b/client/components/Reader/Reader.vue index 0a6dab35..ee89f5af 100644 --- a/client/components/Reader/Reader.vue +++ b/client/components/Reader/Reader.vue @@ -719,15 +719,16 @@ class Reader extends Vue { case 'scrolling': case 'search': case 'copyText': - case 'recentBooks': + case 'refresh': case 'offlineMode': + case 'recentBooks': case 'settings': - if (this[`${button}Active`]) + if (this.progressActive) { + classResult = classDisabled; + } else if (this[`${button}Active`]) { classResult = classActive; + } break; - } - - switch (button) { case 'undoAction': if (this.actionCur <= 0) classResult = classDisabled; From 8df80ce7384ba7ac615e3b4bc179e59f0d437b40 Mon Sep 17 00:00:00 2001 From: Book Pauk Date: Thu, 23 Jan 2020 15:16:49 +0700 Subject: [PATCH 3/8] =?UTF-8?q?=D0=9C=D0=B5=D0=BB=D0=BA=D0=B0=D1=8F=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/api/reader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/api/reader.js b/client/api/reader.js index 47b61c6e..6149a1fc 100644 --- a/client/api/reader.js +++ b/client/api/reader.js @@ -171,7 +171,7 @@ class Reader { //получение файла estSize = (estSize > 0 ? estSize : 1000000); const options = { - onDownloadProgress: progress => { + onDownloadProgress: (progress) => { while (progress.loaded > estSize) estSize *= 1.5; if (callback) From 00cc63b7cd8ed504f1ee0aac5d2cd81da7d3cebc Mon Sep 17 00:00:00 2001 From: Book Pauk Date: Thu, 23 Jan 2020 15:54:46 +0700 Subject: [PATCH 4/8] =?UTF-8?q?WebSocket:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=20get-confi?= =?UTF-8?q?g?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/api/misc.js | 16 ++++++++++++++-- client/api/reader.js | 7 ++----- ...ocketConnection.js => webSocketConnection.js} | 2 +- server/controllers/WebSocketController.js | 12 ++++++++++++ 4 files changed, 29 insertions(+), 8 deletions(-) rename client/api/{WebSocketConnection.js => webSocketConnection.js} (99%) diff --git a/client/api/misc.js b/client/api/misc.js index 79d56d0e..1e63138a 100644 --- a/client/api/misc.js +++ b/client/api/misc.js @@ -1,4 +1,5 @@ import axios from 'axios'; +import wsc from './webSocketConnection'; const api = axios.create({ baseURL: '/api' @@ -6,9 +7,20 @@ const api = axios.create({ class Misc { async loadConfig() { - const response = await api.post('/config', {params: [ + + const query = {params: [ 'name', 'version', 'mode', 'maxUploadFileSize', 'useExternalBookConverter', 'branch', - ]}); + ]}; + + try { + await wsc.open(); + return await wsc.message(wsc.send(Object.assign({action: 'get-config'}, query))); + } catch (e) { + console.error(e); + } + + //если WebSocket проблема, работаем по http + const response = await api.post('/config', query); return response.data; } } diff --git a/client/api/reader.js b/client/api/reader.js index 6149a1fc..1ff1e187 100644 --- a/client/api/reader.js +++ b/client/api/reader.js @@ -1,6 +1,6 @@ import axios from 'axios'; import * as utils from '../share/utils'; -import WebSocketConnection from './WebSocketConnection'; +import wsc from './webSocketConnection'; const api = axios.create({ baseURL: '/api/reader' @@ -12,7 +12,6 @@ const workerApi = axios.create({ class Reader { constructor() { - this.wsc = new WebSocketConnection(); } async getStateFinish(workerId, callback) { @@ -21,7 +20,6 @@ class Reader { let response = {}; try { - const wsc = this.wsc; await wsc.open(); const requestId = wsc.send({action: 'worker-get-state-finish', workerId}); @@ -35,11 +33,10 @@ class Reader { } return response; } catch (e) { - // console.error(e); } - //с WebSocket проблема, проверяем по http + //если WebSocket проблема, работаем по http const refreshPause = 500; let i = 0; response = {}; diff --git a/client/api/WebSocketConnection.js b/client/api/webSocketConnection.js similarity index 99% rename from client/api/WebSocketConnection.js rename to client/api/webSocketConnection.js index a3a67f2b..e5b79789 100644 --- a/client/api/WebSocketConnection.js +++ b/client/api/webSocketConnection.js @@ -169,4 +169,4 @@ class WebSocketConnection { } } -export default WebSocketConnection; \ No newline at end of file +export default new WebSocketConnection(); \ No newline at end of file diff --git a/server/controllers/WebSocketController.js b/server/controllers/WebSocketController.js index 1c9728c9..a3f18098 100644 --- a/server/controllers/WebSocketController.js +++ b/server/controllers/WebSocketController.js @@ -1,4 +1,6 @@ const WebSocket = require ('ws'); +const _ = require('lodash'); + const WorkerState = require('../core/WorkerState');//singleton const utils = require('../core/utils'); @@ -42,6 +44,8 @@ class WebSocketController { switch (req.action) { case 'test': this.test(req, ws); break; + case 'get-config': + this.getConfig(req, ws); break; case 'worker-get-state': this.workerGetState(req, ws); break; case 'worker-get-state-finish': @@ -70,6 +74,14 @@ class WebSocketController { this.send({message: 'Liberama project is awesome'}, req, ws); } + async getConfig(req, ws) { + if (Array.isArray(req.params)) { + this.send(_.pick(this.config, req.params), req, ws); + } else { + throw new Error('params is not an array'); + } + } + async workerGetState(req, ws) { if (!req.workerId) throw new Error(`key 'workerId' is wrong`); From f3da5a902662e35fcbe46d9beea0045411f4c8c5 Mon Sep 17 00:00:00 2001 From: Book Pauk Date: Thu, 23 Jan 2020 15:56:26 +0700 Subject: [PATCH 5/8] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BA=D0=BE=D0=BC=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=80?= =?UTF-8?q?=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/api/misc.js | 2 +- client/api/reader.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/api/misc.js b/client/api/misc.js index 1e63138a..970b4799 100644 --- a/client/api/misc.js +++ b/client/api/misc.js @@ -19,7 +19,7 @@ class Misc { console.error(e); } - //если WebSocket проблема, работаем по http + //если с WebSocket проблема, работаем по http const response = await api.post('/config', query); return response.data; } diff --git a/client/api/reader.js b/client/api/reader.js index 1ff1e187..4ba39515 100644 --- a/client/api/reader.js +++ b/client/api/reader.js @@ -36,7 +36,7 @@ class Reader { console.error(e); } - //если WebSocket проблема, работаем по http + //если с WebSocket проблема, работаем по http const refreshPause = 500; let i = 0; response = {}; From 3456b3d90e82e41480d25ea2e04066e70c8bff21 Mon Sep 17 00:00:00 2001 From: Book Pauk Date: Thu, 23 Jan 2020 16:25:06 +0700 Subject: [PATCH 6/8] =?UTF-8?q?WebSocket:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=20worker-ge?= =?UTF-8?q?t-state-finish,=20=D0=BD=D0=B5=D0=B1=D0=BE=D0=BB=D1=8C=D1=88?= =?UTF-8?q?=D0=BE=D0=B9=20=D1=80=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE=D1=80?= =?UTF-8?q?=D0=B8=D0=BD=D0=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/api/reader.js | 79 ++++++++----------- .../RecentBooksPage/RecentBooksPage.vue | 2 +- server/controllers/WebSocketController.js | 14 ++++ 3 files changed, 46 insertions(+), 49 deletions(-) diff --git a/client/api/reader.js b/client/api/reader.js index 4ba39515..9156c36a 100644 --- a/client/api/reader.js +++ b/client/api/reader.js @@ -14,7 +14,7 @@ class Reader { constructor() { } - async getStateFinish(workerId, callback) { + async getWorkerStateFinish(workerId, callback) { if (!callback) callback = () => {}; let response = {}; @@ -77,12 +77,12 @@ class Reader { callback({totalSteps: 4}); callback(response.data); - response = await this.getStateFinish(workerId, callback); + response = await this.getWorkerStateFinish(workerId, callback); if (response) { if (response.state == 'finish') {//воркер закончил работу, можно скачивать кешированный на сервере файл callback({step: 4}); - const book = await this.loadCachedBook(response.path, callback, false, (response.size ? response.size : -1)); + const book = await this.loadCachedBook(response.path, callback, response.size); return Object.assign({}, response, {data: book.data}); } @@ -100,69 +100,52 @@ class Reader { } } - async checkUrl(url) { - let fileExists = false; + async checkCachedBook(url) { + let estSize = -1; try { - await axios.head(url, {headers: {'Cache-Control': 'no-cache'}}); - fileExists = true; + const response = await axios.head(url, {headers: {'Cache-Control': 'no-cache'}}); + + if (response.headers['content-length']) { + estSize = response.headers['content-length']; + } } catch (e) { - // - } + //восстановим при необходимости файл на сервере из удаленного облака + let response = null + + try { + await wsc.open(); + response = await wsc.message(wsc.send({action: 'reader-restore-cached-file', path: url})); + } catch (e) { + console.error(e); + //если с WebSocket проблема, работаем по http + response = await api.post('/restore-cached-file', {path: url}); + response = response.data; + } - //восстановим при необходимости файл на сервере из удаленного облака - if (!fileExists) { - let response = await api.post('/restore-cached-file', {path: url}); - - const workerId = response.data.workerId; + const workerId = response.workerId; if (!workerId) throw new Error('Неверный ответ api'); - response = await this.getStateFinish(workerId); + response = await this.getWorkerStateFinish(workerId); if (response.state == 'error') { throw new Error(response.error); } + if (response.size && estSize < 0) { + estSize = response.size; + } } - return true; + return estSize; } - async loadCachedBook(url, callback, restore = true, estSize = -1) { + async loadCachedBook(url, callback, estSize = -1) { if (!callback) callback = () => {}; - let response = null; callback({state: 'loading', progress: 0}); //получение размера файла - let fileExists = false; - if (estSize < 0) { - try { - response = await axios.head(url, {headers: {'Cache-Control': 'no-cache'}}); - - if (response.headers['content-length']) { - estSize = response.headers['content-length']; - } - fileExists = true; - } catch (e) { - // - } - } - - //восстановим при необходимости файл на сервере из удаленного облака - if (restore && !fileExists) { - response = await api.post('/restore-cached-file', {path: url}); - - const workerId = response.data.workerId; - if (!workerId) - throw new Error('Неверный ответ api'); - - response = await this.getStateFinish(workerId); - if (response.state == 'error') { - throw new Error(response.error); - } - - if (response.size && estSize < 0) { - estSize = response.size; - } + if (estSize && estSize < 0) { + estSize = await this.checkCachedBook(url); } //получение файла diff --git a/client/components/Reader/RecentBooksPage/RecentBooksPage.vue b/client/components/Reader/RecentBooksPage/RecentBooksPage.vue index e3511dbe..312f5020 100644 --- a/client/components/Reader/RecentBooksPage/RecentBooksPage.vue +++ b/client/components/Reader/RecentBooksPage/RecentBooksPage.vue @@ -272,7 +272,7 @@ class RecentBooksPage extends Vue { async downloadBook(fb2path) { try { - await readerApi.checkUrl(fb2path); + await readerApi.checkCachedBook(fb2path); const d = this.$refs.download; d.href = fb2path; diff --git a/server/controllers/WebSocketController.js b/server/controllers/WebSocketController.js index a3f18098..2bd599e8 100644 --- a/server/controllers/WebSocketController.js +++ b/server/controllers/WebSocketController.js @@ -1,6 +1,8 @@ const WebSocket = require ('ws'); const _ = require('lodash'); +const ReaderWorker = require('../core/Reader/ReaderWorker');//singleton +const ReaderStorage = require('../core/Reader/ReaderStorage');//singleton const WorkerState = require('../core/WorkerState');//singleton const utils = require('../core/utils'); @@ -10,6 +12,8 @@ const closeSocketOnIdle = 5*60*1000;//5 минут class WebSocketController { constructor(wss, config) { this.config = config; + this.readerStorage = new ReaderStorage(); + this.readerWorker = new ReaderWorker(config); this.workerState = new WorkerState(); this.wss = wss; @@ -50,6 +54,8 @@ class WebSocketController { this.workerGetState(req, ws); break; case 'worker-get-state-finish': this.workerGetStateFinish(req, ws); break; + case 'reader-restore-cached-file': + this.readerRestoreCachedFile(req, ws); break; default: throw new Error(`Action not found: ${req.action}`); @@ -118,6 +124,14 @@ class WebSocketController { } } + async readerRestoreCachedFile(req, ws) { + if (!req.path) + throw new Error(`key 'path' is empty`); + + const workerId = this.readerWorker.restoreCachedFile(req.path); + const state = this.workerState.getState(workerId); + this.send((state ? state : {}), req, ws); + } } module.exports = WebSocketController; From 17670aabf9a8e96aaa9434585e514bb3c2526344 Mon Sep 17 00:00:00 2001 From: Book Pauk Date: Thu, 23 Jan 2020 16:59:08 +0700 Subject: [PATCH 7/8] =?UTF-8?q?WebSocket:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=20reader-st?= =?UTF-8?q?orage,=20=D0=BF=D0=BE=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=B1=D0=B0=D0=B3=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/api/reader.js | 15 ++++++-- client/api/webSocketConnection.js | 6 +++- server/controllers/WebSocketController.js | 43 ++++++++++++++++++----- 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/client/api/reader.js b/client/api/reader.js index 9156c36a..2409aefa 100644 --- a/client/api/reader.js +++ b/client/api/reader.js @@ -195,13 +195,22 @@ class Reader { } async storage(request) { - let response = await api.post('/storage', request); + let response = null; + try { + await wsc.open(); + response = await wsc.message(wsc.send({action: 'reader-storage', body: request})); + } catch (e) { + console.error(e); + //если с WebSocket проблема, работаем по http + response = await api.post('/storage', request); + response = response.data; + } - const state = response.data.state; + const state = response.state; if (!state) throw new Error('Неверный ответ api'); - return response.data; + return response; } } diff --git a/client/api/webSocketConnection.js b/client/api/webSocketConnection.js index e5b79789..bbcb21a3 100644 --- a/client/api/webSocketConnection.js +++ b/client/api/webSocketConnection.js @@ -111,7 +111,11 @@ class WebSocketConnection { requestId, timeout, onMessage: (mes) => { - resolve(mes); + if (mes.error) { + reject(mes.error); + } else { + resolve(mes); + } }, onError: (e) => { reject(e); diff --git a/server/controllers/WebSocketController.js b/server/controllers/WebSocketController.js index 2bd599e8..87659128 100644 --- a/server/controllers/WebSocketController.js +++ b/server/controllers/WebSocketController.js @@ -4,6 +4,7 @@ const _ = require('lodash'); const ReaderWorker = require('../core/Reader/ReaderWorker');//singleton const ReaderStorage = require('../core/Reader/ReaderStorage');//singleton const WorkerState = require('../core/WorkerState');//singleton +const log = new (require('../core/AppLogger'))().log;//singleton const utils = require('../core/utils'); const cleanPeriod = 1*60*1000;//1 минута @@ -12,6 +13,8 @@ const closeSocketOnIdle = 5*60*1000;//5 минут class WebSocketController { constructor(wss, config) { this.config = config; + this.isDevelopment = (config.branch == 'development'); + this.readerStorage = new ReaderStorage(); this.readerWorker = new ReaderWorker(config); this.workerState = new WorkerState(); @@ -43,19 +46,25 @@ class WebSocketController { async onMessage(ws, message) { let req = {}; try { + if (this.isDevelopment) { + log(`WebSocket-IN: ${message.substr(0, 4000)}`); + } + ws.lastActivity = Date.now(); req = JSON.parse(message); switch (req.action) { case 'test': - this.test(req, ws); break; + await this.test(req, ws); break; case 'get-config': - this.getConfig(req, ws); break; + await this.getConfig(req, ws); break; case 'worker-get-state': - this.workerGetState(req, ws); break; + await this.workerGetState(req, ws); break; case 'worker-get-state-finish': - this.workerGetStateFinish(req, ws); break; + await this.workerGetStateFinish(req, ws); break; case 'reader-restore-cached-file': - this.readerRestoreCachedFile(req, ws); break; + await this.readerRestoreCachedFile(req, ws); break; + case 'reader-storage': + await this.readerStorageDo(req, ws); break; default: throw new Error(`Action not found: ${req.action}`); @@ -68,10 +77,17 @@ class WebSocketController { send(res, req, ws) { if (ws.readyState == WebSocket.OPEN) { ws.lastActivity = Date.now(); - let r = Object.assign({}, res); + let r = res; if (req.requestId) - r.requestId = req.requestId; - ws.send(JSON.stringify(r)); + r = Object.assign({requestId: req.requestId}, r); + + const message = JSON.stringify(r); + ws.send(message); + + if (this.isDevelopment) { + log(`WebSocket-OUT: ${message.substr(0, 4000)}`); + } + } } @@ -132,6 +148,17 @@ class WebSocketController { const state = this.workerState.getState(workerId); this.send((state ? state : {}), req, ws); } + + async readerStorageDo(req, ws) { + if (!req.body) + throw new Error(`key 'body' is empty`); + if (!req.body.action) + throw new Error(`key 'action' is empty`); + if (!req.body.items || Array.isArray(req.body.data)) + throw new Error(`key 'items' is empty`); + + this.send(await this.readerStorage.doAction(req.body), req, ws); + } } module.exports = WebSocketController; From 1d352a76ceafc4eab8d3834bb76f77e1458e2c9d Mon Sep 17 00:00:00 2001 From: Book Pauk Date: Thu, 23 Jan 2020 17:00:17 +0700 Subject: [PATCH 8/8] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=BE=D0=BF=D0=B5=D1=87=D0=B0=D1=82=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/controllers/ReaderController.js | 4 ++-- server/controllers/WebSocketController.js | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/server/controllers/ReaderController.js b/server/controllers/ReaderController.js index 09596225..5e9a4879 100644 --- a/server/controllers/ReaderController.js +++ b/server/controllers/ReaderController.js @@ -35,9 +35,9 @@ class ReaderController extends BaseController { const request = req.body; let error = ''; try { - if (!request.action) + if (!request.action) throw new Error(`key 'action' is empty`); - if (!request.items || Array.isArray(request.data)) + if (!request.items || Array.isArray(request.data)) throw new Error(`key 'items' is empty`); return await this.readerStorage.doAction(request); diff --git a/server/controllers/WebSocketController.js b/server/controllers/WebSocketController.js index 87659128..33b61a0b 100644 --- a/server/controllers/WebSocketController.js +++ b/server/controllers/WebSocketController.js @@ -150,11 +150,11 @@ class WebSocketController { } async readerStorageDo(req, ws) { - if (!req.body) + if (!req.body) throw new Error(`key 'body' is empty`); - if (!req.body.action) + if (!req.body.action) throw new Error(`key 'action' is empty`); - if (!req.body.items || Array.isArray(req.body.data)) + if (!req.body.items || Array.isArray(req.body.data)) throw new Error(`key 'items' is empty`); this.send(await this.readerStorage.doAction(req.body), req, ws);