【问题标题】:Why is _post_put_hook not running inside a transaction?为什么 _post_put_hook 不在事务中运行?
【发布时间】:2020-01-06 22:09:08
【问题描述】:

我有一些代码可以在_post_put_hook 中排队一个任务。 该任务检索密钥并获取实体。但是,有时工作程序会失败,因为该键的对象尚未创建,但下次运行时会成功。请注意,我们是通过键检索对象,所以我希望数据是一致的。

我只是在提交时调用入队,所以我希望在任务运行时创建对象。在下面的示例中,我发现_post_put_hook 不在事务中,这似乎是导致问题的原因,但为什么不在事务中?

这是一个示例:


    @ndb.synctasklet
    def log_usage(self):
       @ndb.transactional_tasklet(xg=True)
       def _txn():   
           yield Log.insert_document_log_async() 

       yield _txn()


    class Log(ndb.Expando):
        @classmethod
        @ndb.tasklet
        def insert_document_log_async(cls):
            log = cls()
            logging.debug("insert document log in transaction: {}".format(ndb.in_transaction()))
            yield log.put_async()

        @ndb.synctasklet
        def _post_put_hook(self, future):
            @ndb.synctasklet
            def _callback_on_commit():
                key = future.get_result()
                yield SqlTaskHelper.enqueue_syncronise_sql_model_async(key)

            logging.debug("_post_put_hook In transaction: {}".format(ndb.in_transaction()))
            ndb.get_context().call_on_commit(lambda: _callback_on_commit())

代码执行如下:

  1. 调用log_usage 调用insert_document_log_async
  2. 调用insert_document_log_async 时,日志记录表明我们处于事务中(在事务中插入文档日志:True)。
  3. _post_put_hook 日志记录表明我们不在事务中(因此 call_on_commit 会立即执行,我怀疑这是问题所在)。该任务不久后运行,实体并不总是可用。

我想知道为什么_post_put_hook 在事务之外执行。

谢谢

【问题讨论】:

    标签: python google-app-engine app-engine-ndb


    【解决方案1】:

    Google Groups 已回答您的问题。我从那里重新发布:

    “请注意,post 挂钩不会检查 RPC 是否成功。无论由于问题可能发生的失败,挂钩都会运行,更具体地说,contention 也就是您尝试写入单个实体组时另请注意,少量数据存储操作会导致正常操作超时是正常的。阅读更多here 了解最常见的数据存储问题以及here 如何避免争用。

    如果您需要任何编码帮助,我建议您在 Stack Overflow 上发布您的问题,那里的开发人员社区可以更好地为您提供帮助。 Google 网上论坛更侧重于关于 Google Cloud Platform 的一般意见、趋势和一般性质的问题。

    如果 Datastore 检测到异常,则会在代码调用get_result() 时引发异常,因此密钥不会返回。但是,请注意“所有后挂钩在调用签名的末尾都有一个 Future 参数。此 Future 对象保存操作的结果。您可以在此 Future 上调用 get_result 来检索结果;你可以确定 get_result 不会阻塞,since the Future is complete by the time the hook is called.

    也就是说,如果你没有异常,future 已经有了结果,get_result 函数没有阻塞,偶尔会无法检索到密钥。请查看this Stack Overflow 帖子,其中包含解决与您的情况类似的问题的建议。”

    【讨论】:

    • 不,我相信他们误解了这个问题。我们正在检查 get_result 的值,我们没有收到异常。我们遇到的问题是该值在实际提交之前就已排队。因此,当任务首次运行时,该值不可用。在随后的运行中,该值可用并成功。
    猜你喜欢
    • 1970-01-01
    • 2021-05-20
    • 1970-01-01
    • 2015-08-05
    • 2016-03-18
    • 1970-01-01
    • 2021-01-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多