From 8a519f8abc6de772167c2cca101d22ee2052fafc Mon Sep 17 00:00:00 2001 From: Sean Quah <8349537+squahtx@users.noreply.github.com> Date: Tue, 29 Mar 2022 12:31:05 +0100 Subject: [PATCH] Update `LoggingTransaction.call_after` and `call_on_exception` docstrings (#12315) Document the behaviour of `LoggingTransaction.call_after` and `LoggingTransaction.call_on_exception` when transactions are retried. Signed-off-by: Sean Quah --- changelog.d/12315.doc | 1 + synapse/storage/database.py | 23 ++++++++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 changelog.d/12315.doc diff --git a/changelog.d/12315.doc b/changelog.d/12315.doc new file mode 100644 index 0000000000..ed72f55cba --- /dev/null +++ b/changelog.d/12315.doc @@ -0,0 +1 @@ +Document the behaviour of `LoggingTransaction.call_after` and `LoggingTransaction.call_on_exception` methods when transactions are retried. diff --git a/synapse/storage/database.py b/synapse/storage/database.py index 3ef2bdd74b..0264dea61d 100644 --- a/synapse/storage/database.py +++ b/synapse/storage/database.py @@ -241,9 +241,17 @@ class LoggingTransaction: self.exception_callbacks = exception_callbacks def call_after(self, callback: Callable[..., object], *args: Any, **kwargs: Any): - """Call the given callback on the main twisted thread after the - transaction has finished. Used to invalidate the caches on the - correct thread. + """Call the given callback on the main twisted thread after the transaction has + finished. + + Mostly used to invalidate the caches on the correct thread. + + Note that transactions may be retried a few times if they encounter database + errors such as serialization failures. Callbacks given to `call_after` + will accumulate across transaction attempts and will _all_ be called once a + transaction attempt succeeds, regardless of whether previous transaction + attempts failed. Otherwise, if all transaction attempts fail, all + `call_on_exception` callbacks will be run instead. """ # if self.after_callbacks is None, that means that whatever constructed the # LoggingTransaction isn't expecting there to be any callbacks; assert that @@ -254,6 +262,15 @@ class LoggingTransaction: def call_on_exception( self, callback: Callable[..., object], *args: Any, **kwargs: Any ): + """Call the given callback on the main twisted thread after the transaction has + failed. + + Note that transactions may be retried a few times if they encounter database + errors such as serialization failures. Callbacks given to `call_on_exception` + will accumulate across transaction attempts and will _all_ be called once the + final transaction attempt fails. No `call_on_exception` callbacks will be run + if any transaction attempt succeeds. + """ # if self.exception_callbacks is None, that means that whatever constructed the # LoggingTransaction isn't expecting there to be any callbacks; assert that # is not the case.