繁体   English   中英

为什么 firebase cloud-function javascript promise 运行次数超过循环调用次数?

[英]Why does firebase cloud-function javascript promise run more than the number of loop invocations?

我有一个云 function,当销售/购买提交到 Firestore 时触发。 此功能的目的是集中更新库存水平。

如果我只在 1 个仓库更新物品的库存,function 工作得很好,但对多个仓库执行此操作会出现意外行为。 我遍历所有受影响的仓库以计算总库存水平变化,并且每次迭代都会启动 javascript promise。

问题似乎与调用承诺的方式有关。 例如:如果我想更新 3 个仓库并循环 3 次,不知何故 5 个 Promise 正在启动。 这可以通过日志看到。 我在这里研究了类似的问题,但是在 firestore 仍处于测试阶段时提出了解决方案,可能不是正确的前进方向。 Firestore 事务多次触发导致错误数据

这是代码

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)
    })

当循环有 3 个元素但被调用 5 次时的日志消息

我们通过阅读这篇文章找到了解决方案。

一个事务由任意数量的 get() 操作和任意数量的写操作组成,例如 set()、update() 或 delete()。 在并发编辑的情况下,Cloud Firestore 会再次运行整个事务。 例如,如果一个事务读取文档,而另一个客户端修改了这些文档中的任何一个,则 Cloud Firestore 会重试该事务。 此功能可确保事务在最新且一致的数据上运行。

 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM