Процесс узла завершается без ошибок при записи потока в файл - PullRequest
0 голосов
/ 23 октября 2018

Я запускаю автоматизированный процесс, который загружает большой zip-файл, извлекает из этого zip-файла один XML-файл, анализирует соответствующую информацию из XML и затем использует эту проанализированную информацию в другой области.

Этобыл мой оригинальный процесс для загрузки:

import { ParseOne } from 'unzipper';
import Parser from 'node-xml-stream-parser';
import * as http from 'http';

async function download() {
    const stream = await fetchAsStream(url);
    const textFileStream = stream.pipe(ParseOne(filenameInsideZip));
    const parser = new Parser();
    textFileStream.pipe(parser);

    // add event handlers to parser

    await new Promise(resolve => parser.on('finish', resolve));
}

async function fetchAsStream(url) {
    return new Promise((resolve, reject) => {
        return http.get(url, res => {
            if (res.statusCode === 200) resolve(res);
            else reject(new Error(`Failed with status code ${res.statusCode}`));
        });
    });
}

Файл внутри почтового индекса составляет около 170 МБ.Процесс, описанный выше, работал отлично, хотя и немного медленно (около 3 минут).

Однако позже в процессе я использую проанализированные данные для генерации некоторых сценариев SQL.Я не хотел, чтобы отдельные сценарии были слишком большими, поэтому я записываю в файл каждые 10 КБ, а не один файл для всего сценария:

import * as fs from 'fs';

async function generateSqlScripts(data) {
    let script = '...initial stuff...';
    let scriptNumber = 0;

    for (const key of Object.keys(data) {
        script += `Insert Into blah.blah ${key} ${data[key]} ...`;

        if (script.length > 10_000) {
            await new Promise((resolve, reject) =>
                fs.writeFile(scriptPath + scriptNumber, script, err => err ? reject(err) : resolve())
            );
            scriptNumber++;
            script = '';
        }
    }
}

И сразу после записи первого файлаПрограмма умирает без ошибок.После некоторого исследования у меня появилась теория, что это как-то связано с тем фактом, что загруженный файл буферизуется в памяти во время обработки, что может привести к сбою программы.

Чтобы решить эту проблему, Я решил, что вместо обработки загруженных данных по мере их поступления, я должен сохранить данные непосредственно во временный файл, чтобы избежать переполнения памяти, а затем я могу выполнить обработку нового потока из этого файла, который может быть обработанмедленно без переполнения памяти.

Моя новая реализация делает это:

import { ParseOne } from 'unzipper';
import Parser from 'node-xml-stream-parser';
import * as http from 'http';
import * as os from 'os';
import * as fs from 'fs';
import * as path from 'path';

async function download() {
    const stream = await fetchAsStream(url);
    const textFileStream = stream.pipe(ParseOne(filenameInsideZip));

    // NEW STUFF
    const tmpfile = path.join(os.tmpdir(), somePath);
    const writeStream = textFileStream.pipe(fs.createWriteStream(tmpfile, { flags: 'w' });
    await new Promise((resolve, reject) => {
        writeStream.on('end', resolve);
        writeStream.on('error', reject);
    });
    const readStream = fs.createReadStream(tmpfile);
    // END NEW STUFF

    const parser = new Parser();
    readStream.pipe(parser);

    // add event handlers to parser

    await new Promise(resolve => parser.on('finish', resolve));
}

async function fetchAsStream(url) {
    return new Promise((resolve, reject) => {
        return http.get(url, res => {
            if (res.statusCode === 200) resolve(res);
            else reject(new Error(`Failed with status code ${res.statusCode}`));
        });
    });
}

И по какой-то причине, после того как временный файл закончил запись (я убедился, что это работает нормально), программа завершает работубез кода выхода и сообщения об ошибке.

Я прикрепил к процессу uncaughtException и unhandledRejection события и даже добавил хук в process.exit(), чтобы посмотреть, вызывается ли это где-нибудь.И все же я ничего не получаю.

Я считаю себя примерно на уровне 7/10, когда дело доходит до Node, так что это насколько я знаю.

Кто-нибудь знает, что можетбыть не прав с этим процессом, который может быть причиной этих сбоев, или есть какие-либо советы о том, как отладить эту проблему?Я в полной растерянности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...