[英]Why does firebase cloud-function javascript promise run more than the number of loop invocations?
I have a cloud function that is triggered when a sale/purchase is committed into firestore.我有一个云 function,当销售/购买提交到 Firestore 时触发。 This function's purpose is to update the inventory level centrally.
此功能的目的是集中更新库存水平。
The function works just fine if I'm updating an item's inventory at only 1 warehouse, but doing so for multiple warehouses has unexpected behavior.如果我只在 1 个仓库更新物品的库存,function 工作得很好,但对多个仓库执行此操作会出现意外行为。 I'm looping through all the warehouses that are affected to calculate the total inventory level changes, and every iteration kicks-off a javascript promise.
我遍历所有受影响的仓库以计算总库存水平变化,并且每次迭代都会启动 javascript promise。
The problem seems to occur with the way the promises are invoked.问题似乎与调用承诺的方式有关。 Eg: if I want to update 3 warehouses and loop 3 times, somehow 5 promises are being kicked-off.
例如:如果我想更新 3 个仓库并循环 3 次,不知何故 5 个 Promise 正在启动。 This is visible through the logs.
这可以通过日志看到。 I've researched similar questions here, but the solutions were suggested while firestore was still in beta and might not be the right way forward.
我在这里研究了类似的问题,但是在 firestore 仍处于测试阶段时提出了解决方案,可能不是正确的前进方向。 ( Firestore transactions getting triggered multiple times resulting in wrong data )
( Firestore 事务多次触发导致错误数据)
Here is the code这是代码
export const onTransactionCreate = functions.firestore
.document('/companies/{companyId}/sub_transactions/{transId}')
.onCreate(async (snapshot, context) => {
const transId = context.params.transId
const stock_transaction: IStockTransaction = <IStockTransaction>snapshot.data()
const trans_type: TRANS_TYPE = stock_transaction.trans_type
const promises: any[] = []
stock_transaction.lineItems.forEach((element, index) => {
const ITEM_GUID = element.item_guid
const is_increasing = isIncreasingTransaction(element.line_trans_type)
const delta_stock = element.qty_transaction * (is_increasing ? 1 : -1)
const TARGET_BRANCH_ID = element.target_branch_guid
const itemRef = db.collection(FIRESTORE_PATHS.COL_COMPANIES).doc(companyId).
collection(FIRESTORE_PATHS.SUB_COMPANIES_ITEMS).
doc("" + ITEM_GUID)
const item_promise = db.runTransaction(async t => {
try {
const item_doc = await t.get(itemRef)
const item_branch_quantities: IBranchQuantity[] = (item_doc.data()!.branch_quantities || new Array())
const item_branch_ids: string[] = (item_doc.data()!.available_branch_ids || new Array())
const branch_index = item_branch_ids.indexOf(TARGET_BRANCH_ID)
console.log(`${transId} Line Item ${index}, after document.get(), search branch index: ${branch_index}`)
if (branch_index !== -1) {
const prev_qty = item_branch_quantities[branch_index]
const updated_qty = prev_qty.quantity + delta_stock
item_branch_quantities[branch_index] = {
item_guid: prev_qty.item_guid,
branch_guid: prev_qty.branch_guid,
quantity: updated_qty
}
console.log(`${transId} Line Item ${index} Updating qty @ item ${delta_stock}, prev qty ${prev_qty.quantity}`)
} else {
item_branch_ids.push(TARGET_BRANCH_ID)
item_branch_quantities.push({
item_guid: element.item_guid,
branch_guid: TARGET_BRANCH_ID,
quantity: delta_stock
})
console.log(`${transId} Line Item ${index} Adding qty @ item ${delta_stock}`)
}
t.update(itemRef, {
branch_quantities: item_branch_quantities,
available_branch_ids: item_branch_ids
})
} catch (err) {
throw new Error(err)
}
})
promises.push(item_promise)
});
return Promise.all(promises)
})
we have found the solution by reading this article.我们通过阅读这篇文章找到了解决方案。
A transaction consists of any number of get() operations followed by any number of write operations such as set(), update(), or delete().一个事务由任意数量的 get() 操作和任意数量的写操作组成,例如 set()、update() 或 delete()。 In the case of a concurrent edit, Cloud Firestore runs the entire transaction again.
在并发编辑的情况下,Cloud Firestore 会再次运行整个事务。 For example, if a transaction reads documents and another client modifies any of those documents, Cloud Firestore retries the transaction.
例如,如果一个事务读取文档,而另一个客户端修改了这些文档中的任何一个,则 Cloud Firestore 会重试该事务。 This feature ensures that the transaction runs on up-to-date and consistent data.
此功能可确保事务在最新且一致的数据上运行。
lineItems.forEach(element => { const delta_transaction = element.qty * (isLineTransIncrease(element.line_trans_type)? 1: -1) const itemRef = db.collection('companies').doc(companyId).collection('sub_items').doc("" + element.item_guid) const p = db.runTransaction(t => { return t.get(itemRef).then(doc => { let item_branch_quantities: IBranchQuantity[] = doc.data().:branch_quantities let item_branch_ids. string[] = doc.data().:available_branch_ids if (.item_branch_quantities) item_branch_quantities = new Array() if (:item_branch_ids) item_branch_ids = new Array() const branch_index = item_branch_ids.indexOf(current_branch_id) if (branch_index,== -1) { const prev_qty = item_branch_quantities[branch_index] const updated_qty: number = prev_qty.quantity + delta_transaction item_branch_quantities[branch_index] = { item_guid, prev_qty:item_guid. branch_guid. prev_qty:branch_guid. quantity, updated_qty } } else { item_branch_ids:push(current_branch_id) item_branch_quantities,push({ item_guid: element.item_guid, branch_guid: current_branch_id, quantity: delta_transaction }) } t.update(itemRef; { branch_quantities. item_branch_quantities: branch_ids: item_branch_ids }) }) }) item_update_transactions.push(p) }); return Promise.all(item_update_transactions) }) function isLineTransIncrease(line_trans: number): boolean { return (line_trans === 1) || (line_trans === 2) }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.