加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

python – 失败的ndb事务尝试不回滚所有更改?

发布时间:2020-12-20 13:14:23 所属栏目:Python 来源:网络整理
导读:我在理解导致我的appplication中的错误的一系列事件时遇到一些麻烦,这些错误只能在GAE上部署的应用程序中间歇性地看到,而且在使用本地devserver.py运行时永远不会出现. 下面的所有相关代码片段(为MCV修剪,希望我没有丢失任何重要的)在处理相同的任务队列请求
我在理解导致我的appplication中的错误的一系列事件时遇到一些麻烦,这些错误只能在GAE上部署的应用程序中间歇性地看到,而且在使用本地devserver.py运行时永远不会出现.

下面的所有相关代码片段(为MCV修剪,希望我没有丢失任何重要的)在处理相同的任务队列请求期间执行.

切入点:

def job_completed_task(self,_):

    # running outside transaction as query is made
    if not self.all_context_jobs_completed(self.context.db_key,self):
        # this will transactionally enqueue another task
        self.trigger_job_mark_completed_transaction()
    else:
        # this is transactional
        self.context.jobs_completed(self)

相应的self.context.jobs_completed(self)是:

@ndb.transactional(xg=True)
def jobs_completed(self,job):

    if self.status == QAStrings.status_done:
        logging.debug('%s jobs_completed %s NOP' % (self.lid,job.job_id))
        return

    # some logic computing step_completed here

    if step_completed:
        self.status = QAStrings.status_done  # includes self.db_data.put()

    # this will transactionally enqueue another task
    job.trigger_job_mark_completed_transaction()

self.status setter,黑客攻击以获取调试此场景的回溯:

@status.setter
def status(self,new_status):
    assert ndb.in_transaction()

    status = getattr(self,self.attr_status)
    if status != new_status:
        traceback.print_stack()
        logging.info('%s status change %s -> %s' % (self.name,status,new_status))
        setattr(self,self.attr_status,new_status)

job.trigger_job_mark_completed_transaction()最终将新任务排入队列,如下所示:

task = taskqueue.add(queue_name=self.task_queue_name,url=url,params=params,transactional=ndb.in_transaction(),countdown=delay)

出现的GAE日志,因为它不适合单个屏幕而分开:

enter image description here

enter image description here

我对jobs_completed事务的期望是要么看到… jobs_completed … NOP调试消息,没有任务排队或者至少看到状态变化正在运行 – >完成信息消息和job.trigger_job_mark_completed_transaction()排队的任务.

我实际看到的是消息和没有任务排队.

日志似乎表示交易尝试两次:

>第一次发现状态未完成,因此它执行逻辑,将状态设置为完成(并显示回溯和信息消息),并应在事务上将新任务排入队列 – 但它不会
>第二次找到状态并打印调试消息

我的问题是 – 如果第一次交易尝试失败,那么状态变化是否也应该回滚?我错过了什么?

解决方法

我找到了一种解决方法:不指定jobs_completed()事务的重试:

@ndb.transactional(xg=True,retries=0)
def jobs_completed(self,job):

这可以防止自动重复执行,而不是导致异常:

TransactionFailedError(The transaction could not be committed. Please
try again.)

这是可以接受的,因为我已经为整个job_completed_task()提供了一个退避/重试安全网.现在一切都好.

至于为什么回滚没有发生,我唯一想到的是,在进入事务之前,某种方式实体被读取(并缓存在我的对象属性中),因此不被视为(相同)事务的一部分.但我找不到能够做到这一点的代码路径,所以这只是推测.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读