I'm in the process of moving my ndb codebase to async as much as possible where it makes sense. There is a scenario where I'm not quite sure how to proceed: transactions.
As I see it, I have 3 options available:
ndb.transaction()
synchronously, and have the transaction's function call async methods.def option_1():
@ndb.tasklet
def txn():
e = yield Foo.get_by_id_async(some_id)
if e is None:
e = yield Foo().put_async()
raise ndb.Return(e)
# The doc for ndb.transaction() says that it takes a function or tasklet.
# If it's a tasklet, does it wait on the Future that is returned?
# If it doesn't wait, what is the proper way to call a tasklet in a transaction
# and get access to its return value?
return ndb.transaction(txn)
ndb.transaction()
asynchronously, and have the transaction's function call sync methods.@ndb.toplevel
def option_2():
def txn():
e = Foo.get_by_id(some_id)
if e is None:
e = Foo().put()
return e
result = yield ndb.transaction_async(txn)
return result
ndb.transaction()
asynchronously, and have the transaction's function call async methods.@ndb.toplevel
def option_3():
@ndb.tasklet
def txn():
e = yield Foo.get_by_id_async(some_id)
if e is None:
e = yield Foo().put_async()
raise ndb.Return(e)
result = yield ndb.transaction_async(txn)
return result
I feel like option 3 is the one to go to, but I'd rather rely on an expert opinion/advice...
Yeah, #3 is definitely the way to go. The other two have the problem that they mix async and sync code and that's generally not a good thing to do except at the very top level of your app.
PS. Indeed the transaction waits for the callback if it is a tasklet.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With