Repository navigation
fix: roll back session uploads on client disconnect and cancellation - #19
Merged
Merged
Conversation
append_session_video and upload_session_audio only cleaned up on OSError/ValueError, so a stream that ended with starlette's ClientDisconnect or a task cancellation left partial bytes behind: frames.h264 kept the extra chunk while the byte counter stayed at its pre-request value, and a half-uploaded audio.bin blocked a retry with 409. Roll video back to its accepted prefix (and restore the counter) and remove the incomplete audio on every unsuccessful stream exit, then re-raise so cancellation still propagates. Add interrupted-stream tests covering both disconnect and cancellation, including a successful audio retry.
Contributor
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Files Reviewed (5 files)
Reviewed by free · Input: 124.3K · Output: 5.1K · Cached: 64.8K |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #17.
Problem
POST /sessions/{id}/videoandPOST /sessions/{id}/audioonly rolled back onOSError/ValueError. A stream that ends with Starlette'sClientDisconnect(client drops mid-append) or anasyncio.CancelledError(task cancelled) bypassed both handlers:frames.h264kept the partial bytes, while the session'svideo_bytescounter stayed at its pre-request value — a retry could corrupt the elementary stream and the cumulative 2 GB cap no longer matched disk contents.audio.binremained, so the next audio upload was refused with409even though nothing usable had been stored.ClientDisconnectsubclassesException, notOSError/ValueError;CancelledErrorsubclassesBaseException. Both are therefore invisible to a narrower handler.Fix
routes.py:BaseExceptionfor its rollback: on any unsuccessful exit it restoresvideo_bytesto the accepted prefix and truncates or unlinksframes.h264. The rollback stays insideappend_lock, so a queued append cannot snapshot the counter mid-rollback. The exception is re-raised.BaseException, then re-raises.The existing
OSError/ValueErrorouter handling (400 responses) is unchanged.Tests
Four new
pytest.mark.asynciotests call the registered endpoints directly with a request stream that yields a chunk and then disconnects or blocks until cancelled:test_disconnected_video_stream_rolls_back_to_accepted_prefixandtest_cancelled_video_stream_rolls_back_and_preserves_cancellation— assert the exact file contents after rollback, and prove the counter was restored by a follow-up 5-byte append that only fits if the snapshot is correct.test_disconnected_audio_stream_is_removed_and_retry_succeedsandtest_cancelled_audio_stream_is_removed_and_retry_succeeds— assertaudio.binis gone and a normal upload retry succeeds.All four were verified to fail against the unpatched
routes.pyand pass against the fix. Full suite: 37 passed (33 pre-existing + 4 new).plugin.jsonbumped to0.3.2;CHANGELOG.mdandCLAUDE.mdupdated.Note
The audio route's
exists()→open("wb")guard remains non-atomic (pre-existing); overlapping uploads could still race, and the new unlink slightly widens that window. The browser uploads audio at most once per session, so this is out of scope for this fix.big-pickle(free) | 𝕏