Skip to content

fix: prevent intermittent clip splitting failures#403

Open
mvanhorn wants to merge 1 commit intojamiepine:mainfrom
mvanhorn:fix/366-clip-split-race-condition
Open

fix: prevent intermittent clip splitting failures#403
mvanhorn wants to merge 1 commit intojamiepine:mainfrom
mvanhorn:fix/366-clip-split-race-condition

Conversation

@mvanhorn
Copy link
Copy Markdown

@mvanhorn mvanhorn commented Apr 13, 2026

Summary

Addresses the intermittent "Failed to split clip" error reported in #366 with two changes targeting the race condition.

Root cause

split_story_item in backend/services/stories.py queries the item, mutates it, creates a new item, and commits - all without any row locking. Rapid double-clicks (or query invalidation re-renders triggering concurrent mutations) can cause the second request to read stale state from the first, leading to a 404 or inconsistent trim values.

Changes

Backend (backend/services/stories.py): Added with_for_update() to the item query in split_story_item (line 490). This acquires a row-level lock so concurrent split requests on the same clip are serialized rather than racing.

Frontend (app/src/components/StoriesTab/StoryTrackEditor.tsx): Added splitItem.isPending guard to handleSplit (line 503). Prevents the callback from firing while a split mutation is already in flight, which is the most common trigger for the race.

Testing

The race is intermittent by nature, so there's no deterministic repro. The row lock prevents the database-level race, and the isPending guard prevents the UI-level double-fire.

Fixes #366

This contribution was developed with AI assistance (Claude Code).

Summary by CodeRabbit

  • Bug Fixes
    • Improved split operation reliability by preventing new requests from being initiated when another operation is already in progress, reducing duplicate action risks.
    • Implemented database-level locking to safely manage concurrent split attempts and prevent race conditions during simultaneous operations on the same items.

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 jamiepine#366
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 13, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d1a64c49-d37d-4b35-82c0-76fb55e96254

📥 Commits

Reviewing files that changed from the base of the PR and between 75abbb0 and d2a61c9.

📒 Files selected for processing (2)
  • app/src/components/StoriesTab/StoryTrackEditor.tsx
  • backend/services/stories.py

📝 Walkthrough

Walkthrough

The changes address a race condition in the clip splitting feature by adding concurrency safeguards. The frontend prevents initiating multiple concurrent splits via a pending state check, while the backend enforces row-level database locking to ensure consistent reads during split operations.

Changes

Cohort / File(s) Summary
Frontend Concurrency Guard
app/src/components/StoriesTab/StoryTrackEditor.tsx
Added check to prevent split initiation when splitItem.isPending is true, reducing redundant requests during ongoing split operations.
Backend Pessimistic Locking
backend/services/stories.py
Added .with_for_update() to database query in split_story_item to acquire row-level locks on target story items, preventing concurrent modification conflicts.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A rabbit split clips without care,
But races made trouble appear,
With locks and pending checks tight,
The splits now work right—
No more "Failed" messages here! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main objective of the PR: preventing intermittent clip splitting failures through race condition fixes.
Linked Issues check ✅ Passed The PR directly addresses issue #366 by fixing the root cause of intermittent 'Failed to split clip' errors through row-level database locking and UI guards.
Out of Scope Changes check ✅ Passed All changes are tightly scoped to fixing the race condition in clip splitting: backend row locking and frontend UI guard, with no extraneous modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Splitting clips isn't always working

1 participant