Browse Source

Добавлен abort конвертеров при истечении времени ожидания подвижек очереди

Book Pauk 5 năm trước cách đây
mục cha
commit
57fc64af79

+ 5 - 3
server/core/Reader/BookConverter/ConvertBase.js

@@ -14,7 +14,7 @@ class ConvertBase {
         this.calibrePath = `${config.dataDir}/calibre/ebook-convert`;
         this.sofficePath = '/usr/bin/soffice';
         this.pdfToHtmlPath = '/usr/bin/pdftohtml';
-        this.queue = new LimitedQueue(2, 20, 3*60*1000);
+        this.queue = new LimitedQueue(2, 20, 3*60*1000);//3 минуты ожидание подвижек
     }
 
     async run(data, opts) {// eslint-disable-line no-unused-vars
@@ -32,7 +32,7 @@ class ConvertBase {
             throw new Error('Внешний конвертер pdftohtml не найден');
     }
 
-    async execConverter(path, args, onData) {
+    async execConverter(path, args, onData, abort) {
         let q = null;
         try {
             q = await this.queue.get(() => {onData();});
@@ -41,7 +41,7 @@ class ConvertBase {
         }
 
         try {
-            const result = await utils.spawnProcess(path, {args, onData});
+            const result = await utils.spawnProcess(path, {args, onData, abort});
             if (result.code != 0) {
                 let error = result.code;
                 if (this.config.branch == 'development')
@@ -51,6 +51,8 @@ class ConvertBase {
         } catch(e) {
             if (e.status == 'killed') {
                 throw new Error('Слишком долгое ожидание конвертера');
+            } else if (e.status == 'abort') {
+                throw new Error('abort');
             } else if (e.status == 'error') {
                 throw new Error(e.error);
             } else {

+ 3 - 3
server/core/Reader/BookConverter/ConvertDoc.js

@@ -16,7 +16,7 @@ class ConvertDoc extends ConvertDocX {
             return false;
         await this.checkExternalConverterPresent();
 
-        const {inputFiles, callback} = opts;
+        const {inputFiles, callback, abort} = opts;
 
         const outFile = `${inputFiles.filesDir}/${path.basename(inputFiles.sourceFile)}`;
         const docFile = `${outFile}.doc`;
@@ -24,9 +24,9 @@ class ConvertDoc extends ConvertDocX {
         const fb2File = `${outFile}.fb2`;
 
         await fs.copy(inputFiles.sourceFile, docFile);
-        await this.execConverter(this.sofficePath, ['--headless', '--convert-to', 'docx', '--outdir', inputFiles.filesDir, docFile]);
+        await this.execConverter(this.sofficePath, ['--headless', '--convert-to', 'docx', '--outdir', inputFiles.filesDir, docFile], null, abort);
 
-        return await super.convert(docxFile, fb2File, callback);
+        return await super.convert(docxFile, fb2File, callback, abort);
     }
 }
 

+ 4 - 4
server/core/Reader/BookConverter/ConvertDocX.js

@@ -20,12 +20,12 @@ class ConvertDocX extends ConvertBase {
         return false;
     }
 
-    async convert(docxFile, fb2File, callback) {
+    async convert(docxFile, fb2File, callback, abort) {
         let perc = 0;
         await this.execConverter(this.calibrePath, [docxFile, fb2File], () => {
             perc = (perc < 100 ? perc + 5 : 50);
             callback(perc);
-        });
+        }, abort);
 
         return await fs.readFile(fb2File);
     }
@@ -35,7 +35,7 @@ class ConvertDocX extends ConvertBase {
             return false;
         await this.checkExternalConverterPresent();
 
-        const {inputFiles, callback} = opts;
+        const {inputFiles, callback, abort} = opts;
 
         const outFile = `${inputFiles.filesDir}/${path.basename(inputFiles.sourceFile)}`;
         const docxFile = `${outFile}.docx`;
@@ -43,7 +43,7 @@ class ConvertDocX extends ConvertBase {
 
         await fs.copy(inputFiles.sourceFile, docxFile);
 
-        return await this.convert(docxFile, fb2File, callback);
+        return await this.convert(docxFile, fb2File, callback, abort);
     }
 }
 

+ 2 - 2
server/core/Reader/BookConverter/ConvertEpub.js

@@ -28,7 +28,7 @@ class ConvertEpub extends ConvertBase {
             return false;
         await this.checkExternalConverterPresent();
 
-        const {inputFiles, callback} = opts;
+        const {inputFiles, callback, abort} = opts;
 
         const outFile = `${inputFiles.filesDir}/${path.basename(inputFiles.sourceFile)}`;
         const epubFile = `${outFile}.epub`;
@@ -40,7 +40,7 @@ class ConvertEpub extends ConvertBase {
         await this.execConverter(this.calibrePath, [epubFile, fb2File], () => {
             perc = (perc < 100 ? perc + 5 : 50);
             callback(perc);
-        });
+        }, abort);
 
         return await fs.readFile(fb2File);
     }

+ 2 - 2
server/core/Reader/BookConverter/ConvertMobi.js

@@ -16,7 +16,7 @@ class ConvertMobi extends ConvertBase {
             return false;
         await this.checkExternalConverterPresent();
 
-        const {inputFiles, callback} = opts;
+        const {inputFiles, callback, abort} = opts;
 
         const outFile = `${inputFiles.filesDir}/${path.basename(inputFiles.sourceFile)}`;
         const mobiFile = `${outFile}.mobi`;
@@ -28,7 +28,7 @@ class ConvertMobi extends ConvertBase {
         await this.execConverter(this.calibrePath, [mobiFile, fb2File], () => {
             perc = (perc < 100 ? perc + 5 : 50);
             callback(perc);
-        });
+        }, abort);
 
         return await fs.readFile(fb2File);
     }

+ 2 - 2
server/core/Reader/BookConverter/ConvertPdf.js

@@ -18,7 +18,7 @@ class ConvertPdf extends ConvertHtml {
             return false;
         await this.checkExternalConverterPresent();
 
-        const {inputFiles, callback} = opts;
+        const {inputFiles, callback, abort} = opts;
 
         const outFile = `${inputFiles.filesDir}/${utils.randomHexString(10)}.xml`;
 
@@ -27,7 +27,7 @@ class ConvertPdf extends ConvertHtml {
         await this.execConverter(this.pdfToHtmlPath, ['-c', '-s', '-xml', inputFiles.sourceFile, outFile], () => {
             perc = (perc < 80 ? perc + 10 : 40);
             callback(perc);
-        });
+        }, abort);
         callback(80);
 
         const data = await fs.readFile(outFile);

+ 3 - 3
server/core/Reader/BookConverter/ConvertRtf.js

@@ -16,7 +16,7 @@ class ConvertRtf extends ConvertDocX {
             return false;
         await this.checkExternalConverterPresent();
 
-        const {inputFiles, callback} = opts;
+        const {inputFiles, callback, abort} = opts;
 
         const outFile = `${inputFiles.filesDir}/${path.basename(inputFiles.sourceFile)}`;
         const rtfFile = `${outFile}.rtf`;
@@ -24,9 +24,9 @@ class ConvertRtf extends ConvertDocX {
         const fb2File = `${outFile}.fb2`;
 
         await fs.copy(inputFiles.sourceFile, rtfFile);
-        await this.execConverter(this.sofficePath, ['--headless', '--convert-to', 'docx', '--outdir', inputFiles.filesDir, rtfFile]);
+        await this.execConverter(this.sofficePath, ['--headless', '--convert-to', 'docx', '--outdir', inputFiles.filesDir, rtfFile], null, abort);
 
-        return await super.convert(docxFile, fb2File, callback);
+        return await super.convert(docxFile, fb2File, callback, abort);
     }
 }
 

+ 6 - 3
server/core/Reader/BookConverter/index.js

@@ -26,11 +26,14 @@ class BookConverter {
         }
     }
 
-    async convertToFb2(inputFiles, outputFile, opts, callback) {
+    async convertToFb2(inputFiles, outputFile, opts, callback, abort) {
+        if (abort && abort())
+            throw new Error('abort');
+
         const selectedFileType = await this.detector.detectFile(inputFiles.selectedFile);
         const data = await fs.readFile(inputFiles.selectedFile);
 
-        const convertOpts = Object.assign({}, opts, {inputFiles, callback, dataType: selectedFileType});
+        const convertOpts = Object.assign({}, opts, {inputFiles, callback, abort, dataType: selectedFileType});
         let result = false;
         for (const convert of this.convertFactory) {
             result = await convert.run(data, convertOpts);
@@ -41,7 +44,7 @@ class BookConverter {
         }
 
         if (!result && inputFiles.nesting) {
-            result = await this.convertToFb2(inputFiles.nesting, outputFile, opts, callback);
+            result = await this.convertToFb2(inputFiles.nesting, outputFile, opts, callback, abort);
         }
 
         if (!result) {

+ 1 - 1
server/core/Reader/ReaderWorker.js

@@ -27,7 +27,7 @@ class ReaderWorker {
             this.config.tempPublicDir = `${config.publicDir}/tmp`;
             fs.ensureDirSync(this.config.tempPublicDir);
 
-            this.queue = new LimitedQueue(5, 100, 3*60*1000);
+            this.queue = new LimitedQueue(5, 100, 5*60*1000);//5 минут ожидание подвижек
             this.workerState = new WorkerState();
             this.down = new FileDownloader(config.maxUploadFileSize);
             this.decomp = new FileDecompressor(2*config.maxUploadFileSize);

+ 14 - 6
server/core/utils.js

@@ -37,8 +37,8 @@ async function touchFile(filename) {
 }
 
 function spawnProcess(cmd, opts) {
-    let {args, killAfter, onData} = opts;
-    killAfter = (killAfter ? killAfter : 120*1000);
+    let {args, killAfter, onData, abort} = opts;
+    killAfter = (killAfter ? killAfter : 120);//seconds
     onData = (onData ? onData : () => {});
     args = (args ? args : []);
 
@@ -67,10 +67,18 @@ function spawnProcess(cmd, opts) {
             reject({status: 'error', error, stdout, stderr});
         });
 
-        await sleep(killAfter);
-        if (!resolved) {
-            process.kill(proc.pid);
-            reject({status: 'killed', stdout, stderr});
+        while (!resolved) {
+            await sleep(1000);
+            killAfter -= 1;
+            if (killAfter <= 0 || (abort && abort())) {
+                process.kill(proc.pid);
+                if (killAfter <= 0) {
+                    reject({status: 'killed', stdout, stderr});
+                } else {
+                    reject({status: 'abort', stdout, stderr});
+                }
+                break;
+            }
         }
     })().catch(reject); });
 }