使用firebase admin从云功能中的集合中检索数据对大型项目失败。我用来查询云功能选择的示例代码如下
admin.database().orderByChild('mmyyyy').equalTo(month).once('value');
当我尝试检索10600个项目时,此呼叫失败(试图找出原因)。在Google控制台中,有此日志,但没有其他可以将我指向正确方向
textPayload: "Function execution took 18547 ms, finished with status: 'response error'"
尝试失败后,我决定使用Firebase SDK在客户端执行此呼叫,如下所示:
result = await firebase.database().ref(`transactions`).orderByChild('mmyyyy').equalTo(month).once('value');
这在客户端完美地工作,没有错误并返回我所有的17000个项目(此JSON的大小为26MB)。
为什么这样?有没有记录的限制?
注意:我将云功能内存增加到1GB,超时到5分钟,没有帮助。
这是完整的示例代码
const admin = require('firebase-admin');
var functions = require('firebase-functions');
admin.initializeApp(functions.config().firebase);
const cors = require('cors')({
"origin": "*",
"methods": "POST,GET",
"allowedHeaders": "Content-Type,uid,agence,month,course,raceType,raceNumber,status",
"preflightContinue": false,
"optionsSuccessStatus": 204
});
function _findTransactions(agence, month, course, raceType, raceNumber, status) {
return new Promise((resolve, reject) => {
try {
let db = admin.database();
let findPromise = db.ref(`transactions`).orderByChild('mmyyyy').equalTo(month).once('value');
findPromise.then((result) => {
let transactions = result.val();
//removed business logic
resolve(transactions);
}).catch((err) => {
console.log(err);
reject(err);
});
} catch (error) {
console.log(error);
reject(error);
}
});
}
exports.findTransactions = functions.https.onRequest((req, res) => {
let uid;
try {
cors(req, res, () => {
uid = req.headers.uid;
let agence = req.headers.agence;
let month = req.headers.month;
let course = req.headers.course;
let raceType = req.headers.raceType;
let raceNumber = req.headers.raceNumber;
let status = req.headers.status;
if (req.method !== 'GET') {
return handleResponse(req, res, 403);
}
if (!uid || uid == null || uid == undefined) {
return handleResponse(req, res, 401);
}
_validateUserId(uid, ['central_cashier', 'admin'])
.then(() => {
_findTransactions(agence, month, course, raceType, raceNumber, status)
.then((result) => {
return handleResponse(req, res, 200, result);
}).catch((error) => {
return handleResponse(req, res, 500);
});
}).catch((error) => {
return handleResponse(req, res, 401);
});
});
} catch (error) {
return handleError(res, uid, error);
}
});
您的有效载荷太大,如您所述,超出了Google Cloud功能的配额。
想到了两个选项:
- 压缩有效载荷。 GZIP在将文件发送给客户端之前。对于Zlib模块中构建的NodeJS,或; 很容易
- 设置虚拟机。虚拟机不受这些限制。
我进行了一些测试,得出结论,当查询产生大量结果时,Google Cloud功能(GCF)正在执行某种超时或"流产"操作(即许多数据存储实体)。有关某些背景,请参阅我在这个问题上附带的评论。
tl; dr i创建了我自己的Express.js Web服务器,并在其上运行了我的GCF代码。
这是我测试的方式:我使用HTTP/HTTPS创建了一个Ubuntu实例,并启用了DataStore API。在我的情况下,我安装了节点,表达并获得了基本的HTTPS服务器(自签名证书工作正常,因为这只是测试API后端服务)。然后,我将我的GCF代码(在GCF中失败的功能)复制到我的Minimal Express Web服务器中。我指出了我的React应用程序使用我的实例,该应用程序触发了一个查询,从而产生了32,000多个数据存储实体。我的GCF函数发送了一个常见的datastore.runQuery()
查询。
花了大约一分钟的时间,但最终所有32,000个实体都用Express提供并加载在React App(浏览器)中,没有错误。
基本的快速路由调用我的GCF函数:
app.post('/foo', (req, res) => {
myCloudFunction(req, res);
})
const myCloudFunction = (req, res) => {
// Inspects req, queries Datastore, and returns the results.
};
对于此测试,我的React应用只指向https://mydomain.example.com:3000/foo(因为我的Express服务器在端口3000上听)。
所以GCF似乎不够好,除非我在应用程序上添加分页(在路线图上)。