Nicer logging for debusine.server.celery.update_workflows not getting a lock?

When debusine.server.celery.update_workflows cannot get a lock, we get a noisy stack trace in the logs:

Mar 05 10:33:53 <hostname> python3[352730]: Traceback (most recent call last):
Mar 05 10:33:53 <hostname> python3[352730]:   File "/usr/lib/python3/dist-packages/django/db/backends/utils.py", line 89, in _execute
Mar 05 10:33:53 <hostname> python3[352730]:     return self.cursor.execute(sql, params)
Mar 05 10:33:53 <hostname> python3[352730]:            ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
Mar 05 10:33:53 <hostname> python3[352730]:   File "/usr/lib/python3/dist-packages/psycopg/cursor.py", line 97, in execute
Mar 05 10:33:53 <hostname> python3[352730]:     raise ex.with_traceback(None)
Mar 05 10:33:53 <hostname> python3[352730]: psycopg.errors.SerializationFailure: could not serialize access due to concurrent update
Mar 05 10:33:53 <hostname> python3[352730]: The above exception was the direct cause of the following exception:
Mar 05 10:33:53 <hostname> python3[352730]: Traceback (most recent call last):
Mar 05 10:33:53 <hostname> python3[352730]:   File "/usr/lib/python3/dist-packages/celery/app/trace.py", line 453, in trace_task
Mar 05 10:33:53 <hostname> python3[352730]:     R = retval = fun(*args, **kwargs)
Mar 05 10:33:53 <hostname> python3[352730]:                  ~~~^^^^^^^^^^^^^^^^^
Mar 05 10:33:53 <hostname> python3[352730]:   File "/usr/lib/python3/dist-packages/celery/app/trace.py", line 736, in __protected_call__
Mar 05 10:33:53 <hostname> python3[352730]:     return self.run(*args, **kwargs)
Mar 05 10:33:53 <hostname> python3[352730]:            ~~~~~~~~^^^^^^^^^^^^^^^^^
Mar 05 10:33:53 <hostname> python3[352730]:   File "/usr/lib/python3/dist-packages/pgtransaction/transaction.py", line 113, in inner
Mar 05 10:33:53 <hostname> python3[352730]:     return func(*args, **kwds)
Mar 05 10:33:53 <hostname> python3[352730]:   File "/usr/lib/python3/dist-packages/debusine/server/celery.py", line 175, in update_workflows
Mar 05 10:33:53 <hostname> python3[352730]:     ).lock_workflows_for_update()
Mar 05 10:33:53 <hostname> python3[352730]:       ~~~~~~~~~~~~~~~~~~~~~~~~~^^
Mar 05 10:33:53 <hostname> python3[352730]:   File "/usr/lib/python3/dist-packages/debusine/db/models/work_requests.py", line 865, in lock_workflows_for_update
Mar 05 10:33:53 <hostname> python3[352730]:     bool(
Mar 05 10:33:53 <hostname> python3[352730]:     ~~~~^
Mar 05 10:33:53 <hostname> python3[352730]:         WorkRequest.objects.select_for_update(nowait=nowait, no_key=True)
Mar 05 10:33:53 <hostname> python3[352730]:         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Mar 05 10:33:53 <hostname> python3[352730]:     ...<12 lines>...
Mar 05 10:33:53 <hostname> python3[352730]:         .values("id")
Mar 05 10:33:53 <hostname> python3[352730]:         ^^^^^^^^^^^^^
Mar 05 10:33:53 <hostname> python3[352730]:     )
Mar 05 10:33:53 <hostname> python3[352730]:     ^
Mar 05 10:33:53 <hostname> python3[352730]:   File "/usr/lib/python3/dist-packages/django/db/models/query.py", line 414, in __bool__
Mar 05 10:33:53 <hostname> python3[352730]:     self._fetch_all()
Mar 05 10:33:53 <hostname> python3[352730]:     ~~~~~~~~~~~~~~~^^
Mar 05 10:33:53 <hostname> python3[352730]:   File "/usr/lib/python3/dist-packages/django/db/models/query.py", line 1886, in _fetch_all
Mar 05 10:33:53 <hostname> python3[352730]:     self._result_cache = list(self._iterable_class(self))
Mar 05 10:33:53 <hostname> python3[352730]:                          ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Mar 05 10:33:53 <hostname> python3[352730]:   File "/usr/lib/python3/dist-packages/django/db/models/query.py", line 210, in __iter__
Mar 05 10:33:53 <hostname> python3[352730]:     for row in compiler.results_iter(
Mar 05 10:33:53 <hostname> python3[352730]:                ~~~~~~~~~~~~~~~~~~~~~^
Mar 05 10:33:53 <hostname> python3[352730]:         chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size
Mar 05 10:33:53 <hostname> python3[352730]:         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Mar 05 10:33:53 <hostname> python3[352730]:     ):
Mar 05 10:33:53 <hostname> python3[352730]:     ^
Mar 05 10:33:53 <hostname> python3[352730]:   File "/usr/lib/python3/dist-packages/django/db/models/sql/compiler.py", line 1513, in results_iter
Mar 05 10:33:53 <hostname> python3[352730]:     results = self.execute_sql(
Mar 05 10:33:53 <hostname> python3[352730]:         MULTI, chunked_fetch=chunked_fetch, chunk_size=chunk_size
Mar 05 10:33:53 <hostname> python3[352730]:     )
Mar 05 10:33:53 <hostname> python3[352730]:   File "/usr/lib/python3/dist-packages/django/db/models/sql/compiler.py", line 1562, in execute_sql
Mar 05 10:33:53 <hostname> python3[352730]:     cursor.execute(sql, params)
Mar 05 10:33:53 <hostname> python3[352730]:     ~~~~~~~~~~~~~~^^^^^^^^^^^^^
Mar 05 10:33:53 <hostname> python3[352730]:   File "/usr/lib/python3/dist-packages/django/db/backends/utils.py", line 67, in execute
Mar 05 10:33:53 <hostname> python3[352730]:     return self._execute_with_wrappers(
Mar 05 10:33:53 <hostname> python3[352730]:            ~~~~~~~~~~~~~~~~~~~~~~~~~~~^
Mar 05 10:33:53 <hostname> python3[352730]:         sql, params, many=False, executor=self._execute
Mar 05 10:33:53 <hostname> python3[352730]:         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Mar 05 10:33:53 <hostname> python3[352730]:     )
Mar 05 10:33:53 <hostname> python3[352730]:     ^
Mar 05 10:33:53 <hostname> python3[352730]:   File "/usr/lib/python3/dist-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
Mar 05 10:33:53 <hostname> python3[352730]:     return executor(sql, params, many, context)
Mar 05 10:33:53 <hostname> python3[352730]:   File "/usr/lib/python3/dist-packages/django/db/backends/utils.py", line 84, in _execute
Mar 05 10:33:53 <hostname> python3[352730]:     with self.db.wrap_database_errors:
Mar 05 10:33:53 <hostname> python3[352730]:          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Mar 05 10:33:53 <hostname> python3[352730]:   File "/usr/lib/python3/dist-packages/django/db/utils.py", line 91, in __exit__
Mar 05 10:33:53 <hostname> python3[352730]:     raise dj_exc_value.with_traceback(traceback) from exc_value
Mar 05 10:33:53 <hostname> python3[352730]:   File "/usr/lib/python3/dist-packages/django/db/backends/utils.py", line 89, in _execute
Mar 05 10:33:53 <hostname> python3[352730]:     return self.cursor.execute(sql, params)
Mar 05 10:33:53 <hostname> python3[352730]:            ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
Mar 05 10:33:53 <hostname> python3[352730]:   File "/usr/lib/python3/dist-packages/psycopg/cursor.py", line 97, in execute
Mar 05 10:33:53 <hostname> python3[352730]:     raise ex.with_traceback(None)
Mar 05 10:33:53 <hostname> python3[352730]: django.db.utils.OperationalError: could not serialize access due to concurrent update

It looks to me like an expected condition for a task that aims at eventual consistency: would it make sense to catch the OperationalError and log only one line like "update_workflows() deferred due to a concurrent update"?