首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Arango beginTransaction()不回滚trx.abort()

Arango beginTransaction()不回滚trx.abort()
EN

Stack Overflow用户
提问于 2020-01-21 15:48:20
回答 1查看 287关注 0票数 0

我在arangodb.beginTransaction()上遇到了一些困难。在我的测试中,创建事务、通过trx.run() API调用函数然后中止trx并不会回滚数据库中的数据更改。我不清楚发生了什么,而且文档非常稀少。有些文件是相当不祥的,但也非常模糊:

如果给定的函数包含异步逻辑,则只有函数的同步部分将在事务中运行。例如,当使用异步/等待时,只有到第一个等待的代码才会在事务中运行。

在被调用的异步函数中嵌套的异步/等待怎么办?例如,如果我有这个:

代码语言:javascript
运行
复制
async runQuery(query) {
    try {
      const cursor = await this.arangodb.query(query)
      return cursor.all()
    } catch (error) {
      logger.error('ArangoDB query failed', { stack: error })
      throw error
    }
}

async touchDocument(id, revision) {
    const type = await this.getObjectTypeFromId(id)
    const collection = await this.getCollection(type, false, true)
    const idCollection = await this.getCollection(ID_COLLECTION, false, true)
    const touchAql = aql`
      LET permanentDocId = DOCUMENT(${idCollection}, ${id}).docId
      LET permanentDoc = MERGE( DOCUMENT(permanentDocId),  { _rev : ${revision} })
      UPDATE permanentDoc WITH permanentDoc in ${collection} OPTIONS { ignoreRevs: false } 
      RETURN NEW
    `
    return this.runQuery(touchAql)
}

trx.run(() => this.touchDocument(parentId, parentRevision))

this.arangodb.query()是否会在事务中执行?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-01-22 12:52:22

我是阿兰戈斯的作者。对于后人,我想澄清的是,这个答案是关于arangojs 6的,这是在撰写本文时的arangojs的当前版本,以及第一次增加对流事务的支持的版本。API在将来的版本中可能会改变,尽管目前还没有这样做的计划。

由于事务是如何工作的(从arangojs 6开始),您需要特别注意documentation for the run method中提到的警告

如果给定的函数包含异步逻辑,则只有函数的同步部分将在事务中运行。例如,当使用异步/等待时,只有到第一个等待的代码才会在事务中运行。注意下面的例子。

换句话说,如果您只是将async函数包装在trx.run中,那么它们的行为可能会不正确。我建议将事务对象传递给每个函数,并在trx.run中包装这些函数中的方法调用。

例如:

代码语言:javascript
运行
复制
async runQuery(query, trx) {
    try {
      const cursor = await trx.run(() => this.arangodb.query(query))
      return trx.run(() => cursor.all())
    } catch (error) {
      logger.error('ArangoDB query failed', { stack: error })
      throw error
    }
}

async touchDocument(id, revision, trx) {
    const type = await this.getObjectTypeFromId(id, trx)
    const collection = await this.getCollection(type, false, true, trx)
    const idCollection = await this.getCollection(ID_COLLECTION, false, true, trx)
    const touchAql = aql`
      LET permanentDocId = DOCUMENT(${idCollection}, ${id}).docId
      LET permanentDoc = MERGE( DOCUMENT(permanentDocId),  { _rev : ${revision} })
      UPDATE permanentDoc WITH permanentDoc in ${collection} OPTIONS { ignoreRevs: false } 
      RETURN NEW
    `
    return this.runQuery(touchAql, trx)
}

this.touchDocument(parentId, parentRevision, trx)

原因是trx.run将整个驱动程序设置为“事务模式”,执行给定函数,然后在执行“事务模式”后禁用“事务模式”,这样就不会意外地在事务中运行不相关的代码。

这种方法的缺点是,如果函数是异步的,并且包含多个await语句,那么事务中只会运行导致和包含第一个await的代码。在您的代码中,意思是在this.getObjectTypeFromId(id)返回后禁用“事务模式”。如果该方法本身包含多个await表达式,那么同样只有第一个表达式将是事务的一部分(等等)。

我希望这能消除一些混乱。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59844658

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档