From 8df86e6dc8eddbfdc207f5631851a40a959baadd Mon Sep 17 00:00:00 2001 From: Manuel Raynaud Date: Thu, 2 Apr 2026 11:34:49 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F(backend)=20move=20lock=20in?= =?UTF-8?q?=20create=5Ffor=5Fowner=20action=20in=20the=20serializer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For the create_for_owner action, all the db operation are made in the serializer. But the lock of the table was acquired in the viewsets, lot of operation are made between the lock is made and the insert in db. We move the lock operation closer to the insert in the database. We wrap it in a transaction to release the lock once the commit made. --- src/backend/core/api/serializers.py | 19 ++++++++++++++----- src/backend/core/api/viewsets.py | 8 -------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/backend/core/api/serializers.py b/src/backend/core/api/serializers.py index bdb05ce1..83bffc83 100644 --- a/src/backend/core/api/serializers.py +++ b/src/backend/core/api/serializers.py @@ -7,6 +7,7 @@ from base64 import b64decode from os.path import splitext from django.conf import settings +from django.db import connection, transaction from django.db.models import Q from django.utils.functional import lazy from django.utils.text import slugify @@ -505,11 +506,19 @@ class ServerCreateDocumentSerializer(serializers.Serializer): {"content": ["Could not convert content"]} ) from err - document = models.Document.add_root( - title=validated_data["title"], - content=document_content, - creator=user, - ) + with transaction.atomic(): + # locks the table to ensure safe concurrent access + with connection.cursor() as cursor: + cursor.execute( + f'LOCK TABLE "{models.Document._meta.db_table}" ' # noqa: SLF001 + "IN SHARE ROW EXCLUSIVE MODE;" + ) + + document = models.Document.add_root( + title=validated_data["title"], + content=document_content, + creator=user, + ) if user: # Associate the document with the pre-existing user diff --git a/src/backend/core/api/viewsets.py b/src/backend/core/api/viewsets.py index 7c27eb15..80593934 100644 --- a/src/backend/core/api/viewsets.py +++ b/src/backend/core/api/viewsets.py @@ -887,19 +887,11 @@ class DocumentViewSet( permission_classes=[], url_path="create-for-owner", ) - @transaction.atomic def create_for_owner(self, request): """ Create a document on behalf of a specified owner (pre-existing user or invited). """ - # locks the table to ensure safe concurrent access - with connection.cursor() as cursor: - cursor.execute( - f'LOCK TABLE "{models.Document._meta.db_table}" ' # noqa: SLF001 - "IN SHARE ROW EXCLUSIVE MODE;" - ) - # Deserialize and validate the data serializer = serializers.ServerCreateDocumentSerializer(data=request.data) if not serializer.is_valid():