Failed ndb transaction attempt not discarding all changes?

I have some problem understanding the sequence of events that cause an error in my application, which can only be seen intermittently in the application deployed in GAE, and never when working with the local one devserver.py.

All related code fragments below (cut off for MCV, I hope that I have not lost anything significant) are executed during the processing of the request of the same task.

Point of entry:

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)

Relevant 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()

Installer self.statushacked to get traces for debugging this scenario:

@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() ultimately completes the new task as follows:

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

GAE log for the event, broken because it does not fit on one screen:

enter image description here

enter image description here

jobs_completed , ... jobs_completed ... NOP, , , status change running -> done , job.trigger_job_mark_completed_transaction().

, , - , .

, :

  • done, , done ( ) ,

  • 2- done

: , ? ?

+4
1

: jobs_completed():

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

, :

TransactionFailedError ( . .)

, / job_completed_task(). .

, , , , , - ( ) , ) . , , .

0

Source: https://habr.com/ru/post/1657081/


All Articles