Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions invokeai/app/api/routers/videos.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,8 +346,12 @@ async def upload_video(
pass


# Declared sync (`def`, not `async def`) so FastAPI runs it in the threadpool: every call
# below is blocking SQLite/filesystem work, which would stall the event loop — and with it
# every other request and socket event — for the duration of the delete. The batch
# siblings below are sync for the same reason.
@videos_router.delete("/i/{video_name}", operation_id="delete_video", response_model=DeleteVideosResult)
async def delete_video(
def delete_video(
current_user: CurrentUserOrDefault,
video_name: str = PathParam(description="The name of the video to delete"),
) -> DeleteVideosResult:
Expand Down Expand Up @@ -451,8 +455,9 @@ def delete_uncategorized_videos(
)


# Sync for the same reason as delete_video: the update is a blocking SQLite write.
@videos_router.patch("/i/{video_name}", operation_id="update_video", response_model=VideoDTO)
async def update_video(
def update_video(
current_user: CurrentUserOrDefault,
video_name: str = PathParam(description="The name of the video to update"),
video_changes: VideoRecordChanges = Body(description="The changes to apply to the video"),
Expand Down
18 changes: 18 additions & 0 deletions tests/app/routers/test_videos_multiuser.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@
VideoNamesBatch,
_is_mp4_file,
delete_uncategorized_videos,
delete_video,
delete_videos_from_list,
get_video_thumbnail,
star_videos_in_list,
unstar_videos_in_list,
update_video,
)
from invokeai.app.api_app import app
from invokeai.app.services.invoker import Invoker
Expand Down Expand Up @@ -932,3 +934,19 @@ def test_delete_uncategorized_videos_is_offloaded_by_fastapi() -> None:
)
def test_video_batch_mutations_are_offloaded_by_fastapi(handler: Any) -> None:
assert not inspect.iscoroutinefunction(handler)


@pytest.mark.parametrize(
"handler",
[
delete_video,
update_video,
],
)
def test_single_video_mutations_are_offloaded_by_fastapi(handler: Any) -> None:
"""Single-item mutations do blocking SQLite/disk work, same as their batch siblings.

Declared ``async def``, they would run that work directly on the event loop and stall
every other request and socket event until the delete/update finished.
"""
assert not inspect.iscoroutinefunction(handler)
Loading