Python api handle exceptions with @fdb.transactional

Hello,
I am a new user of foundationdb and using it now in our projects. I wonder about using fdb.transactional decorator and handling errors and exceptions.

I wonder if I am missing something is the following example of code (not the final code):

def bank_account(self, params):
      self._fdb_create_accoun(self.db, param)

@fdb.transactional
def _fdb_create_account(tr, param)
     tr['account_id'] = params['name']
     tr['date'] = params['date']

I know that decorator includes a try/except but what happen if transaction failed and what error to handle in caller method bank_account ?

Thank you for advices

The transaction decorator will cause the transaction to automatically retry certain FDB errors. If your function throws a non-FDB error, it would bubble out to bank_account. Additionally, any non-retryable FDB errors will be thrown, as well as any retryable error if you exceed your configured retry limit (based on a transaction option). FDB errors will be of type fdb.FDBError.

1 Like

I second what ajbeamon wrote. Any user exception will not be catched and raise as usual. See

Line 280, the except FDBError will only catch FoundationDB errors.

tr.on_error(...) might raise a FDB error in case the transaction was retried too many times or that is a non-retryable error (e.g. transaction too large ?), and which case the while not commited will stop. Just reading the Python code it seems that the transaction might retry indefinitly, but it is never the case.

By the way, given the fact that a transaction can be retried, you must make sure that the decorated function is idempotent e.g. you can’t send an email inside the transaction function and expect that it will only be sent only-once.

(On a somewhat related note, I am wondering whether the retry logic, should not be the responsability of the bindings instead of the C driver, in some cases you do not want to retry too much time if the transaction happens during an end-user HTTP request-response. One way to workaround it would be to have an “effort” or “timeout” in milliseconds provided by the user, and fallback to another approach in case the transaction can not succeed because of competition. Now that I wrote that, I figured it can be implemented in custom bindings or alternative @transactional decorator)