错误:10已终止:在这些文档上的争用太多.请再试一遍 [英] Error: 10 ABORTED: Too much contention on these documents. Please try again

查看:71
本文介绍了错误:10已终止:在这些文档上的争用太多.请再试一遍的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此错误是什么意思?

特别是什么意思:请重试

这是否意味着事务失败,我必须手动重新运行事务? 根据我对文档的了解,

Does it mean that the transaction failed I have to re-run the transaction manually? From what I understood from the documentation,

该交易读取了在 交易.在这种情况下,交易自动会再次运行. 该交易被重试了有限次.

The transaction read a document that was modified outside of the transaction. In this case, the transaction automatically runs again. The transaction is retried a finite number of times.

如果是,请问哪些文件? 该错误并不表示它正在谈论哪个文档.我刚得到这个堆栈:

If so, on which documents? The error do not indicate which document it is talking about. I just get this stack:

{错误:10已终止:在这些文档上的争用太多.请 再试一次. 在Object.exports.createStatusErrornode_modules \ grpc \ src \ common.js:87:15) 在ClientReadableStream._emitStatusIfDone \ node_modules \ grpc \ src \ client.js:235:26) 在ClientReadableStream._receiveStatus \ node_modules \ grpc \ src \ client.js:213:8) 在Object.onReceiveStatus \ node_modules \ grpc \ src \ client_interceptors.js:1256:15) 在InterceptingListener._callNext node_modules \ grpc \ src \ client_interceptors.js:564:42处) 在InterceptingListener.onReceiveStatus \ node_modules \ grpc \ src \ client_interceptors.js:614:8) 在C:\ Users \ Tolotra Samuel \ PhpstormProjects \ CryptOcean \ node_modules \ grpc \ src \ client_interceptors.js:1019:24 代码:10,元数据:元数据{_internal_repr:{}​​},详细信息:太 这些文件上有很多争论.请再试一遍.' }

{ Error: 10 ABORTED: Too much contention on these documents. Please try again. at Object.exports.createStatusErrornode_modules\grpc\src\common.js:87:15) at ClientReadableStream._emitStatusIfDone \node_modules\grpc\src\client.js:235:26) at ClientReadableStream._receiveStatus \node_modules\grpc\src\client.js:213:8) at Object.onReceiveStatus \node_modules\grpc\src\client_interceptors.js:1256:15) at InterceptingListener._callNext node_modules\grpc\src\client_interceptors.js:564:42) at InterceptingListener.onReceiveStatus\node_modules\grpc\src\client_interceptors.js:614:8) at C:\Users\Tolotra Samuel\PhpstormProjects\CryptOcean\node_modules\grpc\src\client_interceptors.js:1019:24 code: 10, metadata: Metadata { _internal_repr: {} }, details: 'Too much contention on these documents. Please try again.' }

要重新创建此错误,只需按照文档

To recreate this error, just run a for loop on the db.runTransaction method as indicated on the documentation

推荐答案

我们在Firebase Firestore数据库中遇到了同样的问题.即使是只有不到30件商品的小型柜台也遇到了这个问题.

We run into the same problem with the Firebase Firestore database. Even small counters with less then 30 items to cound where running into this issue.

我们的解决方案不是分配计数器,而是增加交易的尝试次数,并为这些重试增加延迟时间.

Our solution was not to distribute the counter but to increase the number of tries for the transaction and to add a deffer time for those retries.

第一步是保存事务操作,因为可以将const witch传递给另一个函数.

The first step was to save the transaction action as const witch could be passed to another function.

const taskCountTransaction = async transaction => {
  const taskDoc = await transaction.get(taskRef)

  if (taskDoc.exists) {
    let increment = 0
    if (change.after.exists && !change.before.exists) {
      increment = 1
    } else if (!change.after.exists && change.before.exists) {
      increment = -1
    }

    let newCount = (taskDoc.data()['itemsCount'] || 0) + increment
    return await transaction.update(taskRef, { itemsCount: newCount > 0 ? newCount : 0 })
  }

  return null
}

第二步是创建两个帮助器函数.一种用于等待指定时间,另一种用于运行事务并捕获错误.如果发生代码为10的中止错误,我们将再次运行该事务以进行特定的重试次数.

The second step was to create two helper functions. One for waiting a specifix amount of time and the other one to run the transaction and catch errors. If the abort error with the code 10 occurs we just run the transaction again for a specific amount of retries.

const wait = ms => { return new Promise(resolve => setTimeout(resolve, ms))}


const runTransaction = async (taskCountTransaction, retry = 0) => {
  try {
    await fs.runTransaction(taskCountTransaction)
    return null
  } catch (e) {
    console.warn(e)
    if (e.code === 10) {
      console.log(`Transaction abort error! Runing it again after ${retry} retries.`)

      if (retry < 4) {
        await wait(1000)
        return runTransaction(taskCountTransaction, ++retry)
      }
    }
  }
}

现在,我们有了所有需要的东西,只需使用await调用帮助函数,我们的事务调用将比默认调用运行更长的时间,并且时间会有所延迟.

Now that we have all we need we can just call our helper function with await and our transaction call will run longer then a default one and it will deffer in time.

await runTransaction(taskCountTransaction)

我对这种解决方案的满意之处在于,它并不意味着要编写更多或复杂的代码,并且大多数已编写的代码都可以保持原样.仅当计数器达到必须对更多项目进行计数的程度时,它才会使用更多的时间和资源.其他时间和资源与您拥有默认事务的时间和资源相同.

What I like about this solution is that it doesn't mean more or complicated code and that most of the already written code can stay as it is. It also uses more time and resources only if the counter gets to the point that it has to count more items. Othervise the time and resources are the same as if you would have the default transactions.

要扩大规模,我们可以增加重试次数或等待时间.两者也都在影响Firebase的成本.对于等待的部分,我们还需要增加函数的超时时间.

For scaling up for large amounts of items we can increase eather the amount of retries or the waiting time. Both are also affecting the costs for Firebase. For the waiting part we also need to increase the timeout for our function.

免责声明:我没有对成千上万个项目进行压力测试.在我们的特定情况下,问题始于20多个项目,而一项任务最多需要50个项目.我用200个项目进行了测试,问题再没有出现.

DISCLAIMER: I have not stress tested this code with thousands or more of items. In our specific case the problems started with 20+ items and we need up to 50 items for a task. I tested it with 200 items and the problem did not apear again.

这篇关于错误:10已终止:在这些文档上的争用太多.请再试一遍的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆