如何强制测试Firestore并行事务在并发场景下的运行正确性?
Cloud Functions 并行事务冲突测试方案(JS/TS)
实现原理
要触发事务冲突,核心是让多个事务实例同时读取到同一份未变更的文档数据,再先后发起写入操作,即可触发数据库的事务冲突校验逻辑。
具体操作步骤
- 提前初始化测试用的目标文档,比如在Firestore中创建
test/targetDoc文档,初始化count字段值为0 - 在待测试的事务逻辑中临时插入等待延迟:在事务读取数据完成后、写入数据前,加入2~3秒的固定等待,保证多个并行事务都能先读取到旧的文档值,不会出现先触发的事务已经写完、后触发的事务才读的情况,示例代码如下:
import * as admin from 'firebase-admin'; const db = admin.firestore(); // 你的待测试云函数 export const transactionHandler = async (req, res) => { try { await db.runTransaction(async (transaction) => { const targetDocRef = db.collection('test').doc('targetDoc'); const docSnap = await transaction.get(targetDocRef); const currentCount = docSnap.data()?.count ?? 0; // 仅测试用临时代码,上线前必须删除 await new Promise(resolve => setTimeout(resolve, 3000)); transaction.update(targetDocRef, { count: currentCount + 1 }); }); res.status(200).send('事务执行完成'); } catch (e) { res.status(500).send('事务执行失败'); } };
- 编写本地触发脚本,批量并行调用云函数,构造多客户端同时请求的场景:
const axios = require('axios'); // 替换为你的测试环境云函数调用地址 const CLOUD_FUNCTION_URL = 'http://localhost:5001/your-project-id/us-central1/transactionHandler'; async function triggerParallelRequests() { // 同时发起5个请求,可根据需要调整并行数量 const requestList = Array.from({ length: 5 }, () => axios.post(CLOUD_FUNCTION_URL)); await Promise.all(requestList); // 验证最终结果 const finalDocSnap = await admin.firestore().collection('test').doc('targetDoc').get(); const finalCount = finalDocSnap.data()?.count; console.log(`并行请求数:5,最终count值:${finalCount}`); // 事务逻辑正常的情况下,finalCount应该等于5,小于5则说明冲突处理逻辑存在问题 } triggerParallelRequests();
注意事项
- 测试完成后必须删除事务中临时添加的延迟代码,避免影响生产环境性能
- 可以调整延迟时长、并行请求数量,模拟不同严重程度的冲突场景
内容的提问来源于stack exchange,提问作者Henrique Bruno
相关产品推荐
相关产品推荐

