Как передавать файл с сервера на Jira с помощью помощника официанта/мультера без утечек памяти

#node.js #memory-leaks #multer #node-streams #busboy

Вопрос:

Настройки:

  1. Я использую node с express для создания сервера.

проблема в том, что:

  1. Я хочу использовать post-запрос для передачи файла/изображения/zip на мой сервер.
  2. с сервера я хочу отправить запрос в JIRA attach file api.
  3. Я хочу сделать это без сохранения файлов в памяти сервера или на локальном диске, т. Е. Я хочу использовать потоки, насколько мне известно.

после некоторых исследований я знаю, что могу использовать помощника официанта или мультера, который построен поверх помощника официанта. однако Малтер не транслирует, поэтому я предпочитаю помощника официанта.

вот мой пример кода:

 const express = require('express')
const Busboy = require('busboy')
const axios = require('axios')
const got = require('got')
const fs = require('fs')
const FormData = require('form-data')
const { Readable, Writable, Transform } = require('stream');

const app = express()
const port = 3000

app.post('/', async(req, res) => {

    const busboy = new Busboy({ headers: req.headers })
    const stream = new Transform();

    busboy.on('file', async function(fieldname, file, filename, encoding, mimetype) {
        stream._transform = function (chunk,encoding,done)
        {
            this.push(chunk)
            done()
        }
        file.pipe(stream)
        const form = new FormData();
        form.append('file', req, { filename: `1gb` });
        try {
            const result = await got.post(`https://<COMPANY>.atlassian.net/rest/api/3/issue/DEVOPS-520/attachments`, {
                headers: {
                Authorization: 'Basic <auth key>',
                    Accept: 'application/json',
                    'X-Atlassian-Token': 'no-check',
            },
            retry: 0,
                body: form,
                responseType: 'json',
        });
            res.sendStatus(200);
        } catch (e) {
            console.log(e)
            res.sendStatus(500);
        }
    })
    busboy.on('finish' , () =>{
        stream.destroy()
    })
    req.pipe(busboy)
})

app.listen(port, () => {
    console.log(`Example app listening at http://localhost:${port}`)
})
 

этот код работает и отправляет файл в JIRA, однако, когда я отслеживаю память процесса sage с помощью системного монитора Linux, я вижу, что используемая им память увеличивается только с каждым вызовом (проверено с файлом 250 МБ). Я вижу, что он увеличивается примерно с 25 МБ до 250 МБ, и каждый вызов увеличивается примерно на 100 МБ. то же самое относится и к тому, когда я пытался использовать мультер.

Я попытался принудительно вызвать сборщик мусора, но то же самое происходит, но с меньшими номерами.

поэтому любая помощь в том, как лучше использовать помощника официанта, почему и где происходит утечка памяти или вообще как лучше использовать потоки в этом коде (мне не нравится тот факт, что мне нужно было использовать transform stream), будет признательна.