Использование @ndb.tasklet или @ndb.synctasklet в Google App Engine

У меня есть метод POST, который вызывает несколько тарелок. Эти цепочки имеют урожайность в них, и у меня есть код x.put_async() в моем коде. Поэтому я не хочу, чтобы он возвращался, прежде чем все асинхронные вещи будут сделаны. Поэтому я украсил все мои талисманы, которые представляют собой небольшие функции с @ndb.tasklet. Кроме того, поверх моего метода POST у меня есть:

@ndb.toplevel
def post(self):

Однако в документации говорится:

Но если метод обработчика использует выход, этот метод все еще должен быть завернутый в другой декоратор, @ndb.synctasklet; в противном случае прекратите выполнение с выходом и не закончите.

Действительно, мой метод имеет выход. Он уже завернут в @ndb.tasklet. Я заменяю это на @ndb.synctasklet или я использую оба (если так, как бы я использовал оба)?

Также см. этот поток, который имеет некоторое значение. Я тоже заметил проблему, когда мой запрос возвращался без вывода, но не воспроизводится. Это происходит каждые 15 минут постоянного использования. У меня был только app = ndb.toplevel(webapp2.WSGIApplication([..]), но теперь я добавил @ndb.toplevel в основные методы POST, но проблема все еще сохраняется.

Должен ли я помещать @ndb.tasklet поверх методов, которые имеют только put_async() тоже? (Должен ли я помещать его поверх каждого метода, чтобы быть в безопасности? Каковы недостатки этого?)

Ответ 1

Относительно обработчика и использования @ndb.toplevel и @ndb.synctasklet: Я понял, что вам нужно использовать как обработчик @ndb.synctasklet, так и @ndb.toplevel. Все подэлементы нужны только декоратору @ndb.tasklet. например.

class Foo(ndb.Model):
    name = ndb.StringProperty()

    @ndb.tasklet
    def my_async(self):
        ....
        #do something else that yields
        raise ndb.Return("some result")   


@ndb.toplevel
@ndb.synctasklet
def post(self):
    foo = Foo(name="baz")
    yield foo.put_async()
    yield foo.my_async()
    ....

Однако. глядя на source, похоже, что @ndb.toplevel на самом деле является синтаксической буквой:

def toplevel(func):
  """A sync tasklet that sets a fresh default Context.

  Use this for toplevel view functions such as
  webapp.RequestHandler.get() or Django view functions.
  """

Выполнение небольшого теста с выходами в обработчике и украшение с помощью @ndb.toplevel все еще работает, и кажется, что вы можете удалить @ndb.synctasklet из обработчика.

Относительно того, следует ли вам включать @ndb.tasklet в методы, вызывающие put_async(): Если вы не уступаете put_async(), вам не нужно включать @ndb.tasklet в окружающий метод (@ndb.toplevel будет обрабатывать результаты с put_async())