Compare commits

...

14 Commits

Author SHA1 Message Date
Book Pauk
f36c13fea1 Merge branch 'release/0.11.8-5' 2022-07-17 21:15:31 +07:00
Book Pauk
4fd9d579e0 Небольшие доработки remoteSent, оптимизация отправки файлов 2022-07-17 21:10:52 +07:00
Book Pauk
e65a8a13ea Рефакторинг 2022-07-17 20:04:23 +07:00
Book Pauk
6ddb97d43e Тюнинг таймаутов 2022-07-17 17:11:34 +07:00
Book Pauk
89082603de Merge tag '0.11.8-4' into develop
0.11.8-4
2022-07-17 16:54:15 +07:00
Book Pauk
a9a3227433 Merge branch 'release/0.11.8-4' 2022-07-17 16:53:59 +07:00
Book Pauk
60cb3514b2 Тюнинг таймаутов 2022-07-17 16:53:12 +07:00
Book Pauk
4aeaa05f0b Merge tag '0.11.8-3' into develop
0.11.8-3
2022-07-17 15:58:34 +07:00
Book Pauk
9c06552278 Merge branch 'release/0.11.8-3' 2022-07-17 15:58:28 +07:00
Book Pauk
000f8dde82 Переход на RemoteStorage 2022-07-17 15:43:12 +07:00
Book Pauk
9ffc218002 Поправка 2022-07-16 21:36:50 +07:00
Book Pauk
68a188f099 Конфиг nginx 2022-07-16 21:10:33 +07:00
Book Pauk
8829bb3810 Конфиг nginx 2022-07-16 21:07:16 +07:00
Book Pauk
5164d2f536 Merge tag '0.11.8-2' into develop
0.11.8-2
2022-07-16 21:02:05 +07:00
9 changed files with 244 additions and 34 deletions

View File

@@ -6,6 +6,7 @@ server {
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
server_name beta.liberama.top; server_name beta.liberama.top;
set $liberama http://127.0.0.1:34082;
client_max_body_size 50m; client_max_body_size 50m;
proxy_read_timeout 1h; proxy_read_timeout 1h;
@@ -15,15 +16,20 @@ server {
gzip_proxied expired no-cache no-store private auth; gzip_proxied expired no-cache no-store private auth;
gzip_types *; gzip_types *;
location @liberama {
proxy_pass $liberama;
}
location /api { location /api {
proxy_pass http://127.0.0.1:34082; proxy_pass $liberama;
} }
location /ws { location /ws {
proxy_pass http://127.0.0.1:34082; proxy_pass $liberama;
proxy_http_version 1.1; proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade"; proxy_set_header Connection "upgrade";
proxy_read_timeout 600s;
} }
location / { location / {
@@ -32,6 +38,11 @@ server {
location /tmp { location /tmp {
types { } default_type "application/xml; charset=utf-8"; types { } default_type "application/xml; charset=utf-8";
add_header Content-Encoding gzip; add_header Content-Encoding gzip;
try_files $uri @liberama;
}
location /upload {
try_files $uri @liberama;
} }
location ~* \.(?:manifest|appcache|html)$ { location ~* \.(?:manifest|appcache|html)$ {
@@ -50,6 +61,7 @@ server {
server { server {
listen 80; listen 80;
server_name b.beta.liberama.top; server_name b.beta.liberama.top;
set $liberama http://127.0.0.1:34082;
client_max_body_size 50m; client_max_body_size 50m;
proxy_read_timeout 1h; proxy_read_timeout 1h;
@@ -59,15 +71,20 @@ server {
gzip_proxied expired no-cache no-store private auth; gzip_proxied expired no-cache no-store private auth;
gzip_types *; gzip_types *;
location @liberama {
proxy_pass $liberama;
}
location /api { location /api {
proxy_pass http://127.0.0.1:34082; proxy_pass $liberama;
} }
location /ws { location /ws {
proxy_pass http://127.0.0.1:34082; proxy_pass $liberama;
proxy_http_version 1.1; proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade"; proxy_set_header Connection "upgrade";
proxy_read_timeout 600s;
} }
location / { location / {
@@ -76,6 +93,11 @@ server {
location /tmp { location /tmp {
types { } default_type "application/xml; charset=utf-8"; types { } default_type "application/xml; charset=utf-8";
add_header Content-Encoding gzip; add_header Content-Encoding gzip;
try_files $uri @liberama;
}
location /upload {
try_files $uri @liberama;
} }
location ~* \.(?:manifest|appcache|html)$ { location ~* \.(?:manifest|appcache|html)$ {

View File

@@ -6,6 +6,7 @@ server {
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
server_name beta.omnireader.ru; server_name beta.omnireader.ru;
set $liberama http://127.0.0.1:34081;
client_max_body_size 50m; client_max_body_size 50m;
proxy_read_timeout 1h; proxy_read_timeout 1h;
@@ -15,15 +16,20 @@ server {
gzip_proxied expired no-cache no-store private auth; gzip_proxied expired no-cache no-store private auth;
gzip_types *; gzip_types *;
location @liberama {
proxy_pass $liberama;
}
location /api { location /api {
proxy_pass http://127.0.0.1:34081; proxy_pass $liberama;
} }
location /ws { location /ws {
proxy_pass http://127.0.0.1:34081; proxy_pass $liberama;
proxy_http_version 1.1; proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade"; proxy_set_header Connection "upgrade";
proxy_read_timeout 600s;
} }
location / { location / {
@@ -32,6 +38,11 @@ server {
location /tmp { location /tmp {
types { } default_type "application/xml; charset=utf-8"; types { } default_type "application/xml; charset=utf-8";
add_header Content-Encoding gzip; add_header Content-Encoding gzip;
try_files $uri @liberama;
}
location /upload {
try_files $uri @liberama;
} }
location ~* \.(?:manifest|appcache|html)$ { location ~* \.(?:manifest|appcache|html)$ {

View File

@@ -1,6 +1,7 @@
server { server {
listen 80; listen 80;
server_name beta.omnireader.ru; server_name beta.omnireader.ru;
set $liberama http://127.0.0.1:34081;
client_max_body_size 50m; client_max_body_size 50m;
proxy_read_timeout 1h; proxy_read_timeout 1h;
@@ -10,15 +11,20 @@ server {
gzip_proxied expired no-cache no-store private auth; gzip_proxied expired no-cache no-store private auth;
gzip_types *; gzip_types *;
location @liberama {
proxy_pass $liberama;
}
location /api { location /api {
proxy_pass http://127.0.0.1:34081; proxy_pass $liberama;
} }
location /ws { location /ws {
proxy_pass http://127.0.0.1:34081; proxy_pass $liberama;
proxy_http_version 1.1; proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade"; proxy_set_header Connection "upgrade";
proxy_read_timeout 600s;
} }
location / { location / {
@@ -27,6 +33,11 @@ server {
location /tmp { location /tmp {
types { } default_type "application/xml; charset=utf-8"; types { } default_type "application/xml; charset=utf-8";
add_header Content-Encoding gzip; add_header Content-Encoding gzip;
try_files $uri @liberama;
}
location /upload {
try_files $uri @liberama;
} }
location ~* \.(?:manifest|appcache|html)$ { location ~* \.(?:manifest|appcache|html)$ {

View File

@@ -39,6 +39,11 @@ module.exports = {
], ],
jembaDb: [ jembaDb: [
{
dbName: 'app',
thread: true,
openAll: true,
},
{ {
dbName: 'reader-storage', dbName: 'reader-storage',
thread: true, thread: true,
@@ -55,8 +60,8 @@ module.exports = {
}, },
], ],
remoteWebDavStorage: false,
/* /*
remoteWebDavStorage: false,
remoteWebDavStorage: { remoteWebDavStorage: {
url: '127.0.0.1:1900', url: '127.0.0.1:1900',
username: '', username: '',
@@ -64,5 +69,12 @@ module.exports = {
}, },
*/ */
remoteStorage: false,
/*
remoteStorage: {
url: 'https://127.0.0.1:11900',
accessToken: '',
},
*/
}; };

View File

@@ -6,7 +6,9 @@ const WorkerState = require('../WorkerState');//singleton
const FileDownloader = require('../FileDownloader'); const FileDownloader = require('../FileDownloader');
const FileDecompressor = require('../FileDecompressor'); const FileDecompressor = require('../FileDecompressor');
const BookConverter = require('./BookConverter'); const BookConverter = require('./BookConverter');
const RemoteWebDavStorage = require('../RemoteWebDavStorage'); const RemoteStorage = require('../RemoteStorage');
const JembaConnManager = require('../../db/JembaConnManager');//singleton
const ayncExit = new (require('../AsyncExit'))();
const utils = require('../utils'); const utils = require('../utils');
const log = new (require('../AppLogger'))().log;//singleton const log = new (require('../AppLogger'))().log;//singleton
@@ -33,10 +35,13 @@ class ReaderWorker {
this.decomp = new FileDecompressor(3*config.maxUploadFileSize); this.decomp = new FileDecompressor(3*config.maxUploadFileSize);
this.bookConverter = new BookConverter(this.config); this.bookConverter = new BookConverter(this.config);
this.remoteWebDavStorage = false; this.connManager = new JembaConnManager();
if (config.remoteWebDavStorage) { this.appDb = this.connManager.db['app'];
this.remoteWebDavStorage = new RemoteWebDavStorage(
Object.assign({maxContentLength: 3*config.maxUploadFileSize}, config.remoteWebDavStorage) this.remoteStorage = false;
if (config.remoteStorage) {
this.remoteStorage = new RemoteStorage(
Object.assign({maxContentLength: 3*config.maxUploadFileSize}, config.remoteStorage)
); );
} }
@@ -235,8 +240,8 @@ class ReaderWorker {
if (!await fs.pathExists(targetName)) { if (!await fs.pathExists(targetName)) {
let found = false; let found = false;
if (this.remoteWebDavStorage) { if (this.remoteStorage) {
found = await this.remoteWebDavStorage.getFileSuccess(targetName, remoteDir); found = await this.remoteStorage.getFileSuccess(targetName, remoteDir);
} }
if (!found) { if (!found) {
@@ -248,12 +253,7 @@ class ReaderWorker {
} }
async cleanDir(dir, remoteDir, maxSize, moveToRemote) { async cleanDir(dir, remoteDir, maxSize, moveToRemote) {
if (!this.remoteSent) const sent = this.remoteSent;
this.remoteSent = {};
if (!this.remoteSent[remoteDir])
this.remoteSent[remoteDir] = {};
const sent = this.remoteSent[remoteDir];
const list = await fs.readdir(dir); const list = await fs.readdir(dir);
@@ -267,24 +267,41 @@ class ReaderWorker {
files.push({name: filePath, stat}); files.push({name: filePath, stat});
} }
} }
log(`clean dir ${dir}, maxSize=${maxSize}, found ${files.length} files, total size=${size}`); log(`clean dir ${dir}, maxSize=${maxSize}, found ${files.length} files, total size=${size}`);
files.sort((a, b) => a.stat.mtimeMs - b.stat.mtimeMs); files.sort((a, b) => a.stat.mtimeMs - b.stat.mtimeMs);
if (moveToRemote && this.remoteWebDavStorage) { //удаленное хранилище
if (moveToRemote && this.remoteStorage) {
const foundFiles = new Set();
for (const file of files) { for (const file of files) {
foundFiles.add(file.name);
if (sent[file.name]) if (sent[file.name])
continue; continue;
//отправляем в remoteWebDavStorage //отправляем в remoteStorage
try { try {
log(`remoteWebDavStorage.putFile ${remoteDir}/${path.basename(file.name)}`); log(`remoteStorage.putFile ${remoteDir}/${path.basename(file.name)}`);
await this.remoteWebDavStorage.putFile(file.name, remoteDir); await this.remoteStorage.putFile(file.name, remoteDir);
sent[file.name] = true; sent[file.name] = true;
await this.appDb.insert({table: 'remote_sent', ignore: true, rows: [{id: file.name, remoteDir}]});
} catch (e) { } catch (e) {
log(LM_ERR, e.stack); log(LM_ERR, e.stack);
} }
} }
//почистим remoteSent и БД
//несколько неоптимально, таскает все записи из БД
const rows = await this.appDb.select({table: 'remote_sent'});
for (const row of rows) {
if (row.remoteDir === remoteDir && !foundFiles.has(row.id)) {
delete sent[row.id];
await this.appDb.delete({table: 'remote_sent', where: `@@id(${this.appDb.esc(row.id)})`});
}
}
} }
let i = 0; let i = 0;
@@ -294,7 +311,9 @@ class ReaderWorker {
const oldFile = file.name; const oldFile = file.name;
//реально удаляем только если сохранили в хранилище или размер dir увеличен в 1.5 раза //реально удаляем только если сохранили в хранилище или размер dir увеличен в 1.5 раза
if ((moveToRemote && this.remoteWebDavStorage && sent[oldFile]) || size > maxSize*1.5) { if (!(moveToRemote && this.remoteStorage)
|| (moveToRemote && this.remoteStorage && sent[oldFile])
|| size > maxSize*1.5) {
await fs.remove(oldFile); await fs.remove(oldFile);
j++; j++;
} }
@@ -302,20 +321,38 @@ class ReaderWorker {
size -= file.stat.size; size -= file.stat.size;
i++; i++;
} }
log(`removed ${j} files`); log(`removed ${j} files`);
} }
async periodicCleanDir(cleanConfig) { async periodicCleanDir(cleanConfig) {
while (1) {// eslint-disable-line no-constant-condition try {
for (const [remoteDir, config] of Object.entries(cleanConfig)) { if (!this.remoteSent)
try { this.remoteSent = {};
await this.cleanDir(config.dir, remoteDir, config.maxSize, config.moveToRemote);
} catch(e) { //инициализация this.remoteSent
log(LM_ERR, e.stack); if (this.remoteStorage) {
const rows = await this.appDb.select({table: 'remote_sent'});
for (const row of rows) {
this.remoteSent[row.id] = true;
} }
} }
await utils.sleep(cleanDirPeriod); while (1) {// eslint-disable-line no-constant-condition
for (const [remoteDir, config] of Object.entries(cleanConfig)) {
try {
await this.cleanDir(config.dir, remoteDir, config.maxSize, config.moveToRemote);
} catch(e) {
log(LM_ERR, e.stack);
}
}
await utils.sleep(cleanDirPeriod);
}
} catch (e) {
log(LM_FATAL, e.message);
ayncExit.exit(1);
} }
} }

View File

@@ -0,0 +1,98 @@
const fs = require('fs-extra');
const path = require('path');
const WebSocketConnection = require('./WebSocketConnection');
class RemoteStorage {
constructor(config) {
this.config = Object.assign({}, config);
this.config.maxContentLength = this.config.maxContentLength || 10*1024*1024;
this.accessToken = this.config.accessToken;
this.wsc = new WebSocketConnection(config.url);
}
async wsRequest(query) {
const response = await this.wsc.message(
await this.wsc.send(Object.assign({accessToken: this.accessToken}, query), 600),
600
);
if (response.error)
throw new Error(response.error);
return response;
}
async wsStat(fileName) {
return await this.wsRequest({action: 'get-stat', fileName});
}
async wsGetFile(fileName) {
return this.wsRequest({action: 'get-file', fileName});
}
async wsPutFile(fileName, data) {//data base64 encoded string
return this.wsRequest({action: 'put-file', fileName, data});
}
async wsDelFile(fileName) {
return this.wsRequest({action: 'del-file', fileName});
}
makeRemoteFileName(fileName, dir = '') {
const base = path.basename(fileName);
if (base.length > 3) {
return `${dir}/${base.substr(0, 3)}/${base}`;
} else {
return `${dir}/${base}`;
}
}
async putFile(fileName, dir = '') {
if (!await fs.pathExists(fileName)) {
throw new Error(`File not found: ${fileName}`);
}
const remoteFilename = this.makeRemoteFileName(fileName, dir);
try {
const localStat = await fs.stat(fileName);
let remoteStat = await this.wsStat(remoteFilename);
remoteStat = remoteStat.stat;
if (remoteStat.isFile && localStat.size == remoteStat.size) {
return;
}
await this.wsDelFile(remoteFilename);
} catch (e) {
//
}
const data = await fs.readFile(fileName, 'base64');
await this.wsPutFile(remoteFilename, data);
}
async getFile(fileName, dir = '') {
if (await fs.pathExists(fileName)) {
return;
}
const remoteFilename = this.makeRemoteFileName(fileName, dir);
const response = await this.wsGetFile(remoteFilename);
await fs.writeFile(fileName, response.data, 'base64');
}
async getFileSuccess(filename, dir = '') {
try {
await this.getFile(filename, dir);
return true;
} catch (e) {
//
}
return false;
}
}
module.exports = RemoteStorage;

View File

@@ -0,0 +1,12 @@
module.exports = {
up: [
['create', {
table: 'remote_sent'
}],
],
down: [
['drop', {
table: 'remote_sent'
}],
]
};

View File

@@ -0,0 +1,6 @@
module.exports = {
table: 'migration1',
data: [
{id: 1, name: 'create', data: require('./001-create')}
]
}

View File

@@ -1,4 +1,5 @@
module.exports = { module.exports = {
'app': require('./app'),
'reader-storage': require('./reader-storage'), 'reader-storage': require('./reader-storage'),
'book-update-server': require('./book-update-server'), 'book-update-server': require('./book-update-server'),
}; };