nodejs: выполнять функцию отображения в пакетах для управления памятью

контекст

Я использую Tabula для разбора таблиц PDF. У меня много PDF-файлов, и у этих PDF-файлов различное количество страниц, от пары до сотен. Я пытаюсь указать моей программе node.js входную папку, и она дает мне csvs всех таблиц, определенных регионами, которые я определил.

Из-за ограничений памяти я не могу просто циклически проходить по файлам, проходить по страницам и иметь табулированный анализ каждой таблицы асинхронно. Поэтому я посмотрел вокруг, как делать пакеты задач и async.mapLimit продолжал подходить. Кажется, что он должен делать то, что мне нужно, но по какой-то причине я получаю только закончить первую партию размера limit и затем он "заканчивается", не переходя к последующим партиям и не выполняя ту же задачу.

Код

const tabula = require('tabula-js');
require('pdfjs-dist');
const fs = require('fs');
const path = require('path');
const async = require('async');

// regions in every page that I care about
const region1 = "5.94,121.275,35.64,788.535";
const region2 = "38.61,159.885,85.14,788.535";
const region3 = "64.35,9.405,149.49,157.905";
const region4 = "87.12,159.885,146.52,789.525";
const region5 = "148.5,186.615,314.82,791.505";
const region6 = "151.47,7.425,313.83,181.665";
const region7 = "318.78,6.435,383.13,788.535";
const region8 = "386.1,10.395,479.16,216.315";
const region9 = "385.11,218.295,595.98,374.715";
const region10 = "386.1,377.685,481.14,791.505";
const region11 = "481.14,10.395,595.98,214.335";
const region12 = "483.12,376.695,596.97,778.635";

// handler for when tabula.js is done extracting table to csv
const handleTableParse = (err, data, title) => {
    if (err) {
        console.log(err);
        return;
    }

    if (!fs.existsSync('./output/')) {
        fs.mkdirSync('./output/');
    }

    if (fs.existsSync(`./output/${title}.csv`)) {
        fs.unlinkSync(`./output/${title}.csv`);
    }

    data.map(line => {
        fs.appendFileSync(`./output/${title}.csv`, `${line}\n`);
    });

}

// parse the tables found on each page in the pdf provided
const parseTablesInPDF = (pdf, numPages) => {

    const pageNumbers = Array.from(new Array(numPages), (x, i) => i + 1);

    const ext = path.extname(pdf);
    const filename = path.basename(pdf, ext)
        .split(' ')
        .join('_');

    // let it do 5 pages at a time for memory management reasons
    async.mapLimit(pageNumbers, 5, pageNumber => {
        const region1Data = tabula(pdf, { pages: `${pageNumber}`, area: region1 });
        region1Data.extractCsv((err, data) => handleTableParse(err, data, `${filename}_region1_page${pageNumber}`));

        const region2Data = tabula(pdf, { pages: `${pageNumber}`, area: region2 });
        region2Data.extractCsv((err, data) => handleTableParse(err, data, `${filename}_region2_page${pageNumber}`));

        const region3Data = tabula(pdf, { pages: `${pageNumber}`, area: region3 });
        region3Data.extractCsv((err, data) => handleTableParse(err, data, `${filename}_region3_page${pageNumber}`));

        const regino4Data = tabula(pdf, { pages: `${pageNumber}`, area: region4 });
        region4Data.extractCsv((err, data) => handleTableParse(err, data, `${filename}_region4_page${pageNumber}`));

        const region5Data = tabula(pdf, { pages: `${pageNumber}`, area: region5 });
        region5Data.extractCsv((err, data) => handleTableParse(err, data, `${filename}_region5_page${pageNumber}`));

        const region6Data = tabula(pdf, { pages: `${pageNumber}`, area: region6 });
        region6Data.extractCsv((err, data) => handleTableParse(err, data, `${filename}_region6_page${pageNumber}`));

        const region7Data = tabula(pdf, { pages: `${pageNumber}`, area: region7 });
        region7Data.extractCsv((err, data) => handleTableParse(err, data, `${filename}_region7_page${pageNumber}`));

        const region8Data = tabula(pdf, { pages: `${pageNumber}`, area: region8 });
        region8Data.extractCsv((err, data) => handleTableParse(err, data, `${filename}_region8_page${pageNumber}`));

        const region9Data = tabula(pdf, { pages: `${pageNumber}`, area: region9 });
        region9Data.extractCsv((err, data) => handleTableParse(err, data, `${filename}_region9_page${pageNumber}`));

        const region10Data = tabula(pdf, { pages: `${pageNumber}`, area: region10 });
        region10Data.extractCsv((err, data) => handleTableParse(err, data, `${filename}_region10_page${pageNumber}`));

        const regino11Data = tabula(pdf, { pages: `${pageNumber}`, area: region11 });
        region11Data.extractCsv((err, data) => handleTableParse(err, data, `${filename}_region11_page${pageNumber}`));

        const region12Data = tabula(pdf, { pages: `${pageNumber}`, area: region12 });
        region12Data.extractCsv((err, data) => handleTableParse(err, data, `${filename}_region12_page${pageNumber}`));
    })
}

// start the process of parsing pdfs, 5 at a time
async.mapLimit(fs.readdirSync('./input/2016'), 5, file => {
    const data = new Uint8Array(fs.readFileSync(`./input/2016/${file}`));
    PDFJS.getDocument(data).then(document => {
        parseTablesInPDF(`./input/2016/${file}`, document.numPages);
    })
}, () => console.log('DONE!'));

проблема

В конце прогона я получаю только 5 страниц каждого PDF-файла, когда знаю, что в нескольких из них содержится более 100 страниц. Кажется, что каждый файл PDF обрабатывается, но по какой-то причине я получаю только 5 страниц для каждого.

Я впервые использую некоторые из этих библиотек. Что я делаю неправильно? Заранее спасибо!

Мои мысли

Может быть, я делаю async.mapLimit внутри async.mapLimit? console.log(pageNumber) Внутри parseTablesInPDF"s async.mapLimit звонок действительно показывает, что я получаю только 1 через 5...

Я молча проваливаюсь? Откуда мне знать?

Обновить

Я понял, что все, что я прошу, чтобы приложение узла выполнялось в одном процессе. Я пытался придумать рабочий пример, я могу обновить этот вопрос, который включает в себя разветвление child_processДа, но я не уверен, как контролировать количество одновременных child_processОни работают сразу. Кажется, что send({...}) Метод асинхронный, и я не уверен, как его "ждать".

Как можно контролировать параллелизм разветвленных дочерних процессов в узле?

0 ответов

Другие вопросы по тегам