Я использую библиотеку aws-sdk-js-v3 для потоковой передачи нескольких наборов данных на один и тот же объект в s3 с использованием одного и того же потока.
import dotenv from 'dotenv'
import {S3} from '@aws-sdk/client-s3'
import { Upload } from '@aws-sdk/lib-storage';
import {PassThrough} from 'stream';
import {randomBytes} from 'crypto'
import { env } from 'process';
export async function finishS3Stream(upload,stream){
stream.end();
await upload.done();
}
export async function writeToStream(stream, data){
// If the stream returns false it represents that the amount of data in the stream has passed the
// highWaterMark threshold and we should wait for a drain event from the stream before continuing to add more data
return new Promise((resolve) => {
if (!stream.write(data)) {
console.info("drain needed")
stream.once('drain', resolve);
} else {
resolve();
}
});
}
export function createS3Stream(key,bucket) {
const client = new S3()
const stream = new PassThrough();
stream.on('error', (e) => console.info(e))
const upload = new Upload({
params: {
Bucket: bucket,
Key: key,
Body: stream,
},
client,
});
return {
stream,
upload,
};
}
async function main(){
dotenv.config()
const bucket = env.BUCKET
const key = env.KEY
console.info("creating stream")
const {stream,upload} = createS3Stream(key,bucket)
const data1 = randomBytes(5242880)
console.info('writing data1 to stream')
await writeToStream(stream,data1)
const data2 = randomBytes(5242880)
console.info('writing data2 to stream')
await writeToStream(stream,data2)
console.info('closing stream')
await finishS3Stream(upload,stream)
}
main()
По какой-то причине основная функция не ожидает, пока поток будет слит, как только он достигнет верхней отметки, и приложение выйдет с кодом выхода 0.
Выход
creating stream
writing data1 to stream
drain needed
Как я могу заставить приложение ждать, пока поток будет слит, и почему оно не ждет, пока обещание будет разрешено, и почему оно завершается перед записью следующего набора данных?
@Svenskunganka не повезло, та же проблема
он не сливается, потому что вы ожидаете метод writeToStream
(он ждет слива), и стим не сливается, пока вы не вызовете finishS3Stream
, который вызовет метод done или класс Upload (он только начинает читать стим там )?
Для тех, кто изо всех сил пытается использовать документацию aws для записи нескольких файлов или нескольких наборов данных в один и тот же поток, вот решение. Вам нужно асинхронно вызвать загрузку, чтобы s3Client начал читать поток. Затем, когда вы его закроете, вам нужно дождаться разрешения функции загрузки.
export async function finishS3Stream(upload,stream){
stream.end();
// wait for the upload promise to resolve
await upload;
}
export async function writeToStream(stream, data){
// If the stream returns false it represents that the amount of data in the stream has passed the
// highWaterMark threshold and we should wait for a drain event from the stream before continuing to add more data
return new Promise((resolve) => {
if (!stream.write(data)) {
console.info("drain needed")
stream.once('drain', resolve);
} else {
resolve();
}
});
}
export function createS3Stream(key,bucket) {
const client = new S3()
const stream = new PassThrough();
stream.on('error', (e) => console.info(e))
// Call done to start reading the string and return a Promise.
const upload = new Upload({
params: {
Bucket: bucket,
Key: key,
Body: stream,
},
client,
}).done();
return {
stream,
upload,
};
}
async function main(){
dotenv.config()
const bucket = env.BUCKET
const key = env.KEY
console.info("creating stream")
const {stream,upload} = createS3Stream(key,bucket)
const data1 = randomBytes(5242880)
console.info('writing data1 to stream')
await writeToStream(stream,data1)
const data2 = randomBytes(5242880)
console.info('writing data2 to stream')
await writeToStream(stream,data2)
console.info('closing stream')
await finishS3Stream(upload,stream)
}
main()
Попробуйте переместить
stream.once('drain', resolve)
выше оператораif
.