From bebec56b1f56ee96c96e4daab0823789bb095dd5 Mon Sep 17 00:00:00 2001 From: Paul Shippy Date: Tue, 28 Apr 2026 10:53:58 +0000 Subject: [PATCH 1/3] Add select_for_update to Flashcard query to fix race condition --- back/bots/models/chat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/bots/models/chat.py b/back/bots/models/chat.py index 9abac72..b5127c7 100644 --- a/back/bots/models/chat.py +++ b/back/bots/models/chat.py @@ -144,7 +144,7 @@ def create_flashcard(deck_name: str, front: str, back: str) -> str: description="" ) deck = Deck.objects.select_for_update().get(pk=deck.pk) - max_order = Flashcard.objects.filter(deck=deck).aggregate(models.Max('order'))['order__max'] or -1 + max_order = Flashcard.objects.select_for_update().filter(deck=deck).aggregate(models.Max('order'))['order__max'] or -1 Flashcard.objects.create( deck=deck, front=front, From 30189c36e167c7638dfd04b316a48ba50fd696dd Mon Sep 17 00:00:00 2001 From: Paul Shippy Date: Tue, 28 Apr 2026 10:58:46 +0000 Subject: [PATCH 2/3] Use order_by('-order').first() instead of aggregate for max_order --- back/bots/models/chat.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/back/bots/models/chat.py b/back/bots/models/chat.py index b5127c7..de9347e 100644 --- a/back/bots/models/chat.py +++ b/back/bots/models/chat.py @@ -144,7 +144,8 @@ def create_flashcard(deck_name: str, front: str, back: str) -> str: description="" ) deck = Deck.objects.select_for_update().get(pk=deck.pk) - max_order = Flashcard.objects.select_for_update().filter(deck=deck).aggregate(models.Max('order'))['order__max'] or -1 + last_card = Flashcard.objects.filter(deck=deck).order_by('-order').first() + max_order = last_card.order if last_card else -1 Flashcard.objects.create( deck=deck, front=front, From ad474e708268c56f5898aca78dc01afff12fc23f Mon Sep 17 00:00:00 2001 From: Paul Shippy Date: Tue, 28 Apr 2026 11:00:44 +0000 Subject: [PATCH 3/3] Remove select_for_update on Deck (no-op on SQLite) --- back/bots/models/chat.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/back/bots/models/chat.py b/back/bots/models/chat.py index de9347e..a2110f1 100644 --- a/back/bots/models/chat.py +++ b/back/bots/models/chat.py @@ -135,7 +135,7 @@ def create_flashcard(deck_name: str, front: str, back: str) -> str: logger.info(f"🃏 CREATE_FLASHCARD_TOOL_INVOKED: deck_name='{deck_name}'") try: with transaction.atomic(): - deck = Deck.objects.select_for_update().filter(profile=self.profile, name=deck_name).first() + deck = Deck.objects.filter(profile=self.profile, name=deck_name).first() if not deck: deck = Deck.objects.create( profile=self.profile, @@ -143,7 +143,6 @@ def create_flashcard(deck_name: str, front: str, back: str) -> str: name=deck_name, description="" ) - deck = Deck.objects.select_for_update().get(pk=deck.pk) last_card = Flashcard.objects.filter(deck=deck).order_by('-order').first() max_order = last_card.order if last_card else -1 Flashcard.objects.create(