Работа над RemoteLib
This commit is contained in:
@@ -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',
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
56
server/core/RemoteLib.js
Normal 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;
|
||||
@@ -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();
|
||||
|
||||
102
server/index.js
102
server/index.js
@@ -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}`);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user