Работа над RemoteLib

This commit is contained in:
Book Pauk
2022-10-07 17:59:34 +07:00
parent 8bec2275ae
commit e6dfe4d221
7 changed files with 155 additions and 66 deletions

View File

@@ -2,7 +2,6 @@ const path = require('path');
const pckg = require('../../package.json');
const execDir = path.resolve(__dirname, '..');
const dataDir = `${execDir}/.${pckg.name}`;
module.exports = {
branch: 'unknown',
@@ -10,10 +9,6 @@ module.exports = {
name: pckg.name,
execDir,
dataDir,
tempDir: `${dataDir}/tmp`,
logDir: `${dataDir}/log`,
publicDir: `${dataDir}/public`,
accessPassword: '',
bookReadLink: '',
@@ -27,6 +22,16 @@ module.exports = {
webConfigParams: ['name', 'version', 'branch', 'bookReadLink'],
allowRemoteLib: false,
remoteLib: false,
/*
allowRemoteLib: true, // на сервере
remoteLib: { // на клиенте
accessPassword: '',
url: 'wss://remoteInpxWeb.ru',
},
*/
server: {
ip: '0.0.0.0',
port: '22380',

View File

@@ -1,4 +1,5 @@
const _ = require('lodash');
const path = require('path');
const fs = require('fs-extra');
const branchFilename = __dirname + '/application_env';
@@ -12,6 +13,8 @@ const propsToSave = [
'cacheCleanInterval',
'inpxCheckInterval',
'lowMemoryMode',
'allowRemoteLib',
'remoteLib',
'server',
];
@@ -29,7 +32,7 @@ class ConfigManager {
return instance;
}
async init() {
async init(dataDir) {
if (this.inited)
throw new Error('already inited');
@@ -44,10 +47,17 @@ class ConfigManager {
process.env.NODE_ENV = this.branch;
this.branchConfigFile = __dirname + `/${this.branch}.js`;
this._config = require(this.branchConfigFile);
const config = require(this.branchConfigFile);
await fs.ensureDir(this._config.dataDir);
this._userConfigFile = `${this._config.dataDir}/config.json`;
if (dataDir) {
config.dataDir = path.resolve(dataDir);
} else {
config.dataDir = `${config.execDir}/.${config.name}`;
}
await fs.ensureDir(config.dataDir);
this._userConfigFile = `${config.dataDir}/config.json`;
this._config = config;
this.inited = true;
}

View File

@@ -1,18 +1,12 @@
const path = require('path');
const pckg = require('../../package.json');
const base = require('./base');
const execDir = path.dirname(process.execPath);
const dataDir = `${execDir}/.${pckg.name}`;
module.exports = Object.assign({}, base, {
branch: 'production',
execDir,
dataDir,
tempDir: `${dataDir}/tmp`,
logDir: `${dataDir}/log`,
publicDir: `${dataDir}/public`,
server: {
ip: '0.0.0.0',

View File

@@ -1,5 +1,6 @@
const WebSocket = require ('ws');
const fs = require('fs-extra');
const _ = require('lodash');
const WebSocket = require ('ws');
const WorkerState = require('../core/WorkerState');//singleton
const WebWorker = require('../core/WebWorker');//singleton
@@ -83,6 +84,9 @@ class WebSocketController {
case 'get-book-link':
await this.getBookLink(req, ws); break;
case 'get-inpx-file':
await this.getInpxFile(req, ws); break;
default:
throw new Error(`Action not found: ${req.action}`);
}
@@ -162,6 +166,16 @@ class WebSocketController {
this.send(result, req, ws);
}
async getInpxFile(req, ws) {
if (!this.config.allowRemoteLib)
throw new Error('Remote lib access disabled');
const data = await fs.readFile(this.config.inpxFile, 'base64');
this.send({data}, req, ws);
}
}
module.exports = WebSocketController;

56
server/core/RemoteLib.js Normal file
View File

@@ -0,0 +1,56 @@
const fs = require('fs-extra');
const utils = require('./utils');
const WebSocketConnection = require('./WebSocketConnection');
//singleton
let instance = null;
class RemoteLib {
constructor(config) {
if (!instance) {
this.config = config;
this.wsc = new WebSocketConnection(config.remoteLib.url, 10, 30, {rejectUnauthorized: false});
if (config.remoteLib.accessPassword)
this.accessToken = utils.getBufHash(config.remoteLib.accessPassword, 'sha256', 'hex');
this.inpxFile = `${config.tempDir}/${utils.randomHexString(20)}`;
this.lastUpdateTime = 0;
instance = this;
}
return instance;
}
async wsRequest(query) {
if (this.accessToken)
query.accessToken = this.accessToken;
const response = await this.wsc.message(
await this.wsc.send(query, 60),
60
);
if (response.error)
throw new Error(response.error);
return response;
}
async getInpxFile(getPeriod = 0) {
if (getPeriod && Date.now() - this.lastUpdateTime < getPeriod)
return this.inpxFile;
const response = await this.wsRequest({action: 'get-inpx-file'});
await fs.writeFile(this.inpxFile, response.data, 'base64');
this.lastUpdateTime = Date.now();
return this.inpxFile;
}
}
module.exports = RemoteLib;

View File

@@ -5,11 +5,12 @@ const zlib = require('zlib');
const _ = require('lodash');
const ZipReader = require('./ZipReader');
const WorkerState = require('./WorkerState');
const WorkerState = require('./WorkerState');//singleton
const { JembaDbThread } = require('jembadb');
const DbCreator = require('./DbCreator');
const DbSearcher = require('./DbSearcher');
const InpxHashCreator = require('./InpxHashCreator');
const RemoteLib = require('./RemoteLib');//singleton
const ayncExit = new (require('./AsyncExit'))();
const log = new (require('./AppLogger'))().log;//singleton
@@ -505,6 +506,11 @@ class WebWorker {
while (this.myState != ssNormal)
await utils.sleep(1000);
if (this.config.remoteLib) {
const remoteLib = new RemoteLib(this.config);
await remoteLib.getInpxFile(60*1000);
}
const newInpxHash = await inpxHashCreator.getHash();
const dbConfig = await this.dbConfig();

View File

@@ -6,16 +6,18 @@ const compression = require('compression');
const http = require('http');
const WebSocket = require ('ws');
const ayncExit = new (require('./core/AsyncExit'))();
const RemoteLib = require('./core/RemoteLib');//singleton
const utils = require('./core/utils');
const ayncExit = new (require('./core/AsyncExit'))();
const maxPayloadSize = 50;//in MB
let log;
let config;
let argv;
let branch = '';
const argvStrings = ['lib-dir', 'inpx'];
const argvStrings = ['lib-dir', 'app-dir', 'inpx'];
function showHelp() {
console.log(utils.versionText(config));
@@ -24,6 +26,7 @@ function showHelp() {
Options:
--help Print ${config.name} command line options
--app-dir=<dirpath> Set application working directory, default: "<execDir>/.${config.name}"
--lib-dir=<dirpath> Set library directory, default: the same as ${config.name} executable's
--inpx=<filepath> Set INPX collection file, default: the one that found in library dir
--recreate Force recreation of the search database on start
@@ -33,25 +36,30 @@ Options:
async function init() {
argv = require('minimist')(process.argv.slice(2), {string: argvStrings});
const dataDir = argv['app-dir'];
//config
const configManager = new (require('./config'))();//singleton
await configManager.init();
//configManager.userConfigFile = argv.config;
await configManager.init(dataDir);
await configManager.load();
config = configManager.config;
branch = config.branch;
//dirs
config.tempDir = `${config.dataDir}/tmp`;
config.logDir = `${config.dataDir}/log`;
config.publicDir = `${config.dataDir}/public`;
configManager.config = config;
await fs.ensureDir(config.dataDir);
await fs.ensureDir(config.tempDir);
await fs.emptyDir(config.tempDir);
//logger
const appLogger = new (require('./core/AppLogger'))();//singleton
await appLogger.init(config);
log = appLogger.log;
//dirs
await fs.ensureDir(config.dataDir);
await fs.ensureDir(config.tempDir);
await fs.emptyDir(config.tempDir);
//web app
if (branch !== 'development') {
const createWebApp = require('./createWebApp');
@@ -67,52 +75,49 @@ async function init() {
log('Initializing');
}
const libDir = argv['lib-dir'];
if (libDir) {
if (await fs.pathExists(libDir)) {
config.libDir = libDir;
} else {
throw new Error(`Directory "${libDir}" not exists`);
}
} else {
config.libDir = config.execDir;
}
if (argv.inpx) {
if (await fs.pathExists(argv.inpx)) {
config.inpxFile = argv.inpx;
} else {
throw new Error(`File "${argv.inpx}" not found`);
}
} else {
const inpxFiles = [];
await utils.findFiles((file) => {
if (path.extname(file) == '.inpx')
inpxFiles.push(file);
}, config.libDir, false);
if (inpxFiles.length) {
if (inpxFiles.length == 1) {
config.inpxFile = inpxFiles[0];
if (!config.remoteLib) {
const libDir = argv['lib-dir'];
if (libDir) {
if (await fs.pathExists(libDir)) {
config.libDir = libDir;
} else {
throw new Error(`Found more than one .inpx files: \n${inpxFiles.join('\n')}`);
throw new Error(`Directory "${libDir}" not exists`);
}
} else {
throw new Error(`No .inpx files found here: ${config.libDir}`);
config.libDir = config.execDir;
}
if (argv.inpx) {
if (await fs.pathExists(argv.inpx)) {
config.inpxFile = argv.inpx;
} else {
throw new Error(`File "${argv.inpx}" not found`);
}
} else {
const inpxFiles = [];
await utils.findFiles((file) => {
if (path.extname(file) == '.inpx')
inpxFiles.push(file);
}, config.libDir, false);
if (inpxFiles.length) {
if (inpxFiles.length == 1) {
config.inpxFile = inpxFiles[0];
} else {
throw new Error(`Found more than one .inpx files: \n${inpxFiles.join('\n')}`);
}
} else {
throw new Error(`No .inpx files found here: ${config.libDir}`);
}
}
} else {
const remoteLib = new RemoteLib(config);
config.inpxFile = await remoteLib.getInpxFile();
}
config.recreateDb = argv.recreate || false;
config.inpxFilterFile = `${config.execDir}/inpx-web-filter.json`;
config.allowUnsafeFilter = argv['unsafe-filter'] || false;
//app
const appDir = `${config.publicDir}/app`;
const appNewDir = `${config.publicDir}/app_new`;
if (await fs.pathExists(appNewDir)) {
await fs.remove(appDir);
await fs.move(appNewDir, appDir);
}
}
async function main() {
@@ -124,10 +129,8 @@ async function main() {
const server = http.createServer(app);
const wss = new WebSocket.Server({ server, maxPayload: maxPayloadSize*1024*1024 });
const serverConfig = Object.assign({}, config, config.server);
let devModule = undefined;
if (serverConfig.branch == 'development') {
if (branch == 'development') {
const devFileName = './dev.js'; //require ignored by pkg -50Mb executable size
devModule = require(devFileName);
devModule.webpackDevMiddleware(app);
@@ -152,6 +155,7 @@ async function main() {
});
}
const serverConfig = config.server;
server.listen(serverConfig.port, serverConfig.ip, () => {
log(`Server is ready on http://${serverConfig.ip}:${serverConfig.port}`);
});