fix: prevent intermittent clip splitting failures (#403)

Two changes to address the race condition causing "Failed to split clip":

Backend (stories.py): Added with_for_update() to the item query in
split_story_item so concurrent requests for the same clip are
serialized via a row lock instead of racing.

Frontend (StoryTrackEditor.tsx): Guard handleSplit with
splitItem.isPending to prevent rapid double-clicks from firing
multiple mutations before the first completes.

Fixes #366

Co-authored-by: Matt Van Horn <[email protected]>
This commit is contained in:
Matt Van Horn
2026-04-16 01:51:15 -07:00
committed by GitHub
co-authored by Matt Van Horn
parent 9a3c307c75
commit 13ba5f1aa6
2 changed files with 4 additions and 2 deletions
@@ -500,7 +500,7 @@ export function StoryTrackEditor({ storyId, items }: StoryTrackEditorProps) {
}, [trimmingItem, trimSide, tempTrimValues, storyId, trimItem, toast]);
const handleSplit = useCallback(() => {
if (!selectedClipId) return;
if (!selectedClipId || splitItem.isPending) return;
const item = items.find((i) => i.id === selectedClipId);
if (!item) return;
+3 -1
View File
@@ -484,13 +484,15 @@ async def split_story_item(
Returns:
List of two updated item details (original and new) or None if not found/invalid
"""
# Get the item
# Get the item with a row lock to prevent concurrent splits on the
# same clip (e.g. from rapid double-clicks racing each other).
item = (
db.query(DBStoryItem)
.filter_by(
id=item_id,
story_id=story_id,
)
.with_for_update()
.first()
)
if not item: