🐛(backend) manage race condition when creating sandbox document

When a user is created and a sandbox document should be created, we can
have a race condition on the document creation leading to an error for
the user. To avoid this we have to manage this part in a transaction and
locking the document table
This commit is contained in:
Manuel Raynaud
2026-03-12 13:51:41 +01:00
parent e36366b293
commit 2eb2641d2c
4 changed files with 64 additions and 26 deletions
@@ -114,7 +114,7 @@ def test_models_invitations_new_user_convert_invitations_to_accesses():
).exists() # the other invitation remains
def test_models_invitationd_new_user_filter_expired_invitations():
def test_models_invitations_new_user_filter_expired_invitations():
"""
Upon creating a new identity, valid invitations should be converted into accesses
and expired invitations should remain unchanged.
@@ -145,7 +145,7 @@ def test_models_invitationd_new_user_filter_expired_invitations():
@pytest.mark.parametrize("num_invitations, num_queries", [(0, 3), (1, 7), (20, 7)])
def test_models_invitationd_new_userd_user_creation_constant_num_queries(
def test_models_invitations_new_userd_user_creation_constant_num_queries(
django_assert_num_queries, num_invitations, num_queries
):
"""
+30 -3
View File
@@ -3,6 +3,7 @@ Unit tests for the User model
"""
import uuid
from concurrent.futures import ThreadPoolExecutor
from unittest.mock import patch
from django.core.exceptions import ValidationError
@@ -188,9 +189,8 @@ def test_models_users_handle_onboarding_documents_on_restricted_document_is_not_
"""On-boarding document can be used when restricted"""
document = factories.DocumentFactory(link_reach=models.LinkReachChoices.RESTRICTED)
settings.USER_ONBOARDING_DOCUMENTS = [str(document.id)]
user = factories.UserFactory()
with override_settings(USER_ONBOARDING_DOCUMENTS=[str(document.id)]):
user = factories.UserFactory()
assert not models.LinkTrace.objects.filter(user=user, document=document).exists()
@@ -302,3 +302,30 @@ def test_models_users_duplicate_onboarding_sandbox_document_integration_with_oth
document=sandbox_doc, user=user, role=models.RoleChoices.OWNER
).exists()
assert models.LinkTrace.objects.filter(document=onboarding_doc, user=user).exists()
@pytest.mark.django_db(transaction=True)
def test_models_users_duplicate_onboarding_sandbox_race_condition():
"""
It should be possible to create several documents at the same time
without causing any race conditions or data integrity issues.
"""
def create_user():
return factories.UserFactory()
template_document = factories.DocumentFactory(title="Getting started with Docs")
with (
override_settings(
USER_ONBOARDING_SANDBOX_DOCUMENT=str(template_document.id),
),
ThreadPoolExecutor(max_workers=2) as executor,
):
future1 = executor.submit(create_user)
future2 = executor.submit(create_user)
user1 = future1.result()
user2 = future2.result()
assert isinstance(user1, models.User)
assert isinstance(user2, models.User)