Firebase 函数 Node.js 转换流
Firebase function Node.js transform stream
我正在创建一个 Firebase HTTP 函数,它进行 BigQuery 查询和 returns 查询结果的修改版本。查询可能 returns 数百万行,因此我无法在响应 HTTP 客户端之前将整个查询结果存储在内存中。我正在尝试使用 Node.js 流,并且由于我需要在将结果发送到客户端之前修改结果,所以我正在尝试使用转换流。但是,当我尝试通过转换流传输查询流时,Firebase 函数崩溃并显示以下错误消息:finished with status: 'response error'
.
我的最小可重现示例如下。我正在使用缓冲区,因为我不想一次处理一行(块),因为我需要进行异步网络调用来转换数据。
return new Promise((resolve, reject) => {
const buffer = new Array(5000)
let bufferIndex = 0
const [job] = await bigQuery.createQueryJob(options)
const bqStream = job.getQueryResultsStream()
const transformer = new Transform({
writableObjectMode: true,
readableObjectMode: false,
transform(chunk, enc, callback) {
buffer[bufferIndex] = chunk
if (bufferIndex < buffer.length - 1) {
bufferIndex++
}
else {
this.push(JSON.stringify(buffer).slice(1, -1)) // Transformation should happen here.
bufferIndex = 0
}
callback()
},
flush(callback) {
if (bufferIndex > 0) {
this.push(JSON.stringify(buffer.slice(0, bufferIndex)).slice(1, -1))
}
this.push("]")
callback()
},
})
bqStream
.pipe(transform)
.pipe(response)
bqStream.on("end", () => {
resolve()
})
}
I cannot store the entire query result in memory before responding to the HTTP client
不幸的是,当使用 Cloud Functions 时,这正是必须发生的事情。
响应负载有 10MB 的 documented 限制,当您的代码继续写入响应时,它会有效地存储在内存中。不支持流式传输请求和响应。
一种替代方法是将您的响应写入 Cloud Storage 中的对象,然后将 link 或对该文件的引用发送给客户端,以便它可以从该对象中完整读取响应。
如果您需要发送大型流式响应,Cloud Functions 不是一个好的选择。同样受限的 Cloud 运行 也不是。您将需要研究其他允许直接套接字访问的解决方案,例如 Compute Engine。
我正在创建一个 Firebase HTTP 函数,它进行 BigQuery 查询和 returns 查询结果的修改版本。查询可能 returns 数百万行,因此我无法在响应 HTTP 客户端之前将整个查询结果存储在内存中。我正在尝试使用 Node.js 流,并且由于我需要在将结果发送到客户端之前修改结果,所以我正在尝试使用转换流。但是,当我尝试通过转换流传输查询流时,Firebase 函数崩溃并显示以下错误消息:finished with status: 'response error'
.
我的最小可重现示例如下。我正在使用缓冲区,因为我不想一次处理一行(块),因为我需要进行异步网络调用来转换数据。
return new Promise((resolve, reject) => {
const buffer = new Array(5000)
let bufferIndex = 0
const [job] = await bigQuery.createQueryJob(options)
const bqStream = job.getQueryResultsStream()
const transformer = new Transform({
writableObjectMode: true,
readableObjectMode: false,
transform(chunk, enc, callback) {
buffer[bufferIndex] = chunk
if (bufferIndex < buffer.length - 1) {
bufferIndex++
}
else {
this.push(JSON.stringify(buffer).slice(1, -1)) // Transformation should happen here.
bufferIndex = 0
}
callback()
},
flush(callback) {
if (bufferIndex > 0) {
this.push(JSON.stringify(buffer.slice(0, bufferIndex)).slice(1, -1))
}
this.push("]")
callback()
},
})
bqStream
.pipe(transform)
.pipe(response)
bqStream.on("end", () => {
resolve()
})
}
I cannot store the entire query result in memory before responding to the HTTP client
不幸的是,当使用 Cloud Functions 时,这正是必须发生的事情。
响应负载有 10MB 的 documented 限制,当您的代码继续写入响应时,它会有效地存储在内存中。不支持流式传输请求和响应。
一种替代方法是将您的响应写入 Cloud Storage 中的对象,然后将 link 或对该文件的引用发送给客户端,以便它可以从该对象中完整读取响应。
如果您需要发送大型流式响应,Cloud Functions 不是一个好的选择。同样受限的 Cloud 运行 也不是。您将需要研究其他允许直接套接字访问的解决方案,例如 Compute Engine。