我有一个Cloud Firestore触发器,负责调整应用程序中用户钱包的余额。
exports.onCreateTransaction = functions.firestore
.document('accounts/{accountId}/transactions/{transactionId}')
.onCreate(async (snap, context) => {
const { accountId, transactionId } = context.params;
const transaction = snap.data();
// See the implementation of alreadyTriggered in the next code block
const alreadyTriggered = await firestoreHelpers.triggers.alreadyTriggered(context);
if (alreadyTriggered) {
return null;
}
if (transaction.status === 'confirmed') {
const accountRef = firestore
.collection('accounts')
.doc(accountId);
const account = (await accountRef.get()).data();
const balance = transaction.type === 'deposit' ?
account.balance + transaction.amount :
account.balance - transaction.amount;
await accountRef.update({ balance });
}
return snap.ref.update({ id: transactionId });
});
由于触发器实际上可能被调用不止一次,我添加了alreadyTriggered
辅助函数:
const alreadyTriggered = (event) => {
return firestore.runTransaction(async transaction => {
const { eventId } = event;
const metaEventRef = firestore.doc(`metaEvents/${eventId}`);
const metaEvent = await transaction.get(metaEventRef);
if (metaEvent.exists) {
console.error(`Already triggered function for event: ${eventId}`);
return true;
} else {
await transaction.set(metaEventRef, event);
return false;
}
})
};
大多数时候,一切都按预期进行。然而,今天我遇到了一个超时错误,导致数据库中的数据不一致。
函数执行耗时60005毫秒,完成状态为:"超时">
超时的原因是什么?我如何确保这种情况不再发生,以便我的交易金额成功反映在账户余额中?
如前所述,关于多次执行的语句是测试版的限制。云功能测试版现已失效。默认情况下,当前担保至少执行一次。如果在云控制台中启用重试,则只能获得多个可能的事件。如果你想确保你的事件得到可靠的处理,这是你应该做的事情。
超时的原因可能永远都不确定。原因可能有很多。也许是网络出现了问题,或者是系统中某个地方出现了短暂的停机时间。重试应该通过多次潜在地传递事件来帮助您从这些临时情况中恢复,这样您的功能才能成功。