-
Notifications
You must be signed in to change notification settings - Fork 68
Description
Hello again,
I hope your life is going well with the COVID19 drama.
This could either be a question or a feature request depending on your answer.
I noticed in the commit and PR history the fact that the new datastore does not support nested transactions and hence NDB also will not support it moving forward.
Nonetheless, we have cases where standalone methods need to be transactional and then, inadvertently, one may call another:
@ndb.transactional()
def do_thing(*args):
...
@ndb.transactional()
def do_another_thing(*args):
do_thing(*args)
...
The use case easy to see: functions that are composable and some are transactional, they are bound to intersect.
I did the following workaround; my rationale being, if no nested transaction is supported anyway this is the best we can do. I have an ersats decorator that I use:
def ndb_transactional(*nargs, **nkwargs):
def outter_wrap(func):
@wraps(func)
def inner_wrap(*args, **kwargs):
if ndb.in_transaction():
return func(*args, **kwargs)
else:
return ndb.transactional(*nargs, **nkwargs)(func)(*args, **kwargs)
return inner_wrap
return outter_wrap
So if we are already in a transaction we will continue calling the wrapped function, else we will continue with the original ndb.transactional(). This coupled with a warning informing that there is no such thing as a nested transaction anymore could potentially handle these cases.
Should you decide this is not a good feature request, I would be interested in your reasoning or whether or not you think this approach could have some unexpected consequence. Thank you very much.
UPDATE: to be clear, I am suggesting that ndb.transactional checks for an existing transaction and either continues if one exists or starts one if it doesn't. If one exists already it logs a warning.