движок приложения связывает отложенные транзакционные задачи

Когда я вызываю отложенную транзакционную задачу из транзакционной функции, f, f могут фиксировать, пока отложенная задача не выполняется.

ОДНАКО, если я вызываю f через отложенный вызов, вызывающая функция завершается ошибкой.

Для воспроизведения я сделал следующее:

@ndb.transactional()
def f():
  # modify datastore entity X
  ... 
  x.put()

class X(ndb.Model):
  ...
  def _post_put_hook(self, future)
    deferred.defer(y,
                   _transactional=ndb.in_transaction())
def y():
  raise Exception()

Когда я вызываю f, отложенная задача терпит неудачу, но x.put() фиксируется.

ОДНАКО, если я вызову deferred.f, x.put() завершится ошибкой.


person user7650840    schedule 03.03.2017    source источник


Ответы (1)


Я думаю, вы неправильно поняли, что делает необязательный аргумент _transactional в deferred.defer(y, _transactional=ndb.in_transaction()). Это не означает, что отложенное выполнение y произойдет в той же транзакции, в которой была вызвана deferred.defer(), это означает только, что постановка отложенной задачи в очередь произойдет, если транзакция завершится успешно. .

Из google.appengine.ext.deferred .deferred модуль:

google.appengine.ext.deferred.deferred.defer(obj, *args, **kwargs)

[...]

  • obj — вызываемый объект для выполнения. См. строку документации модуля для ограничений. _countdown, _eta, _headers, _name, _target, _transactional, _url, _retry_options, _queue: передано в очередь задач — подробности см. в документации по очереди задач.

И из модуль google.appengine.api.taskqueue.taskqueue:

добавить(задача, транзакция=False)

[...]

  • транзакционный — если True, транзакционные задачи будут добавлены в очередь, но не могут быть запущены или переданы в аренду до тех пор, пока транзакция не завершится успешно. Если транзакция завершится неудачно, задачи будут удалены из очереди (и, следовательно, никогда не будут выполняться). Если False, добавленные задачи доступны для немедленного запуска; успех или неудача любой включающей транзакции игнорируется.

Фактическое выполнение отложенной задачи выполняется по другому запросу, всегда в контексте транзакции, отличном от того, в котором была вызвана deferred.defer(). Вот почему ваша отложенная задача может завершиться неудачно, даже если исходная транзакция прошла успешно.

person Dan Cornilescu    schedule 08.12.2017