我有收集投票提交并将它们存储在 Cassandra 中的 Node 应用程序。投票存储为 base64 编码的加密字符串。API 有一个名为的端点/export
,它应该获取所有这些投票字符串(可能 > 100 万),将它们转换为二进制文件并将它们一个接一个地附加到 votes.egd 文件中。然后应该压缩该文件并将其发送给客户端。我的想法是从 Cassandra 流式传输行,将每个投票字符串转换为二进制文件并写入WriteStream
. 我想将此功能包装在 Promise 中以便于使用。我有以下内容:
streamVotesToFile(query, validVotesFileBasename) {
return new Promise((resolve, reject) => {
const writeStream = fs.createWriteStream(`${validVotesFileBasename}.egd`);
writeStream.on('error', (err) => {
logger.error(`Writestream ${validVotesFileBasename}.egd error`);
reject(err);
});
writeStream.on('drain', () => {
logger.info(`Writestream ${validVotesFileBasename}.egd error`);
})
db.client.stream(query)
.on('readable', function() {
let row = this.read();
while (row) {
const envelope = new Buffer(row.vote, 'base64');
if(!writeStream.write(envelope + '\n')) {
logger.error(`Couldn't write vote`);
}
row = this.read()
}
})
.on('end', () => { // No more rows from Cassandra
writeStream.end();
writeStream.on('finish', () => {
logger.info(`Stream done writing`);
resolve();
});
})
.on('error', (err) => { // err is a response error from Cassandra
reject(err);
});
});
}
当我运行它时,它会将所有投票附加到文件并下载正常。但是我有很多问题/疑问:
如果我向
/export
端点发出请求并且此函数运行,则在它运行时对应用程序的所有其他请求都非常慢,或者只是在导出请求完成之前没有完成。我猜是因为事件循环被 Cassandra 流中的所有这些事件占用(每秒数千个)?所有的投票似乎都很好地写入了文件,但我
false
几乎每次writeStream.write()
通话都会收到相应的记录消息(见代码)?我知道我需要考虑 WritableStream 的背压和“排水”事件,所以理想情况下我会使用
pipe()
投票并将其传送到一个文件,因为它内置了背压支持(对吗?)但是因为我需要处理每一行(转换到二进制并可能在将来添加来自其他行字段的其他数据),我将如何用管道做到这一点?