mirror of
https://github.com/jamiepine/voicebox.git
synced 2026-10-04 01:25:18 -07:00
fix(versions): don't let a locked version file abort the delete cascade
This commit is contained in:
committed by
capy-ai-staging[bot]
parent
4750b47b04
commit
64b4b976d6
@@ -4,6 +4,7 @@ Generation history management module.
|
||||
|
||||
from typing import List, Optional, Tuple
|
||||
from datetime import UTC, datetime
|
||||
import logging
|
||||
import uuid
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
@@ -14,6 +15,8 @@ from ..models import GenerationRequest, GenerationResponse, HistoryQuery, Histor
|
||||
from ..database import Generation as DBGeneration, GenerationVersion as DBGenerationVersion, StoryItem as DBStoryItem, VoiceProfile as DBVoiceProfile
|
||||
from .. import config
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _delete_generation_children(generation_id: str, db: Session) -> None:
|
||||
"""Remove the rows that reference a generation, plus any version audio files.
|
||||
@@ -334,7 +337,7 @@ async def delete_failed_generations(db: Session) -> int:
|
||||
except OSError:
|
||||
# Best-effort cleanup — don't abort the whole sweep
|
||||
# if a single file can't be removed.
|
||||
pass
|
||||
logger.warning("Could not delete generation audio %s", audio_path)
|
||||
|
||||
db.delete(generation)
|
||||
count += 1
|
||||
@@ -372,7 +375,7 @@ async def delete_generations_by_profile(
|
||||
except OSError:
|
||||
# A file locked by playback shouldn't abort the whole sweep
|
||||
# and leave the profile half-deleted.
|
||||
pass
|
||||
logger.warning("Could not delete generation audio %s", audio_path)
|
||||
|
||||
# Delete from database
|
||||
db.delete(generation)
|
||||
|
||||
@@ -8,6 +8,7 @@ version and any number of processed versions with different effects chains.
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import logging
|
||||
import uuid
|
||||
from pathlib import Path
|
||||
from typing import List, Optional
|
||||
@@ -21,6 +22,8 @@ from ..database import (
|
||||
from ..models import GenerationVersionResponse, EffectConfig
|
||||
from .. import config
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _version_response(v: DBGenerationVersion) -> GenerationVersionResponse:
|
||||
"""Convert a DB version row to a Pydantic response."""
|
||||
@@ -185,7 +188,15 @@ def delete_version(version_id: str, db: Session) -> bool:
|
||||
|
||||
|
||||
def delete_versions_for_generation(generation_id: str, db: Session) -> int:
|
||||
"""Delete all versions for a generation (used when deleting a generation)."""
|
||||
"""Delete all versions for a generation (used when deleting a generation).
|
||||
|
||||
This runs as part of a wider cascade — deleting one generation, sweeping
|
||||
failed ones, or deleting a whole profile. A version file the OS won't let
|
||||
us remove (locked by playback on Windows) must not abort that cascade and
|
||||
strand the caller half-deleted, so the row goes regardless and the leaked
|
||||
file is logged. ``delete_version`` keeps raising, because a single
|
||||
user-initiated delete should fail loudly.
|
||||
"""
|
||||
versions = (
|
||||
db.query(DBGenerationVersion)
|
||||
.filter_by(generation_id=generation_id)
|
||||
@@ -195,7 +206,12 @@ def delete_versions_for_generation(generation_id: str, db: Session) -> int:
|
||||
for v in versions:
|
||||
audio_path = config.resolve_storage_path(v.audio_path)
|
||||
if audio_path is not None and audio_path.exists():
|
||||
audio_path.unlink()
|
||||
try:
|
||||
audio_path.unlink()
|
||||
except OSError:
|
||||
logger.warning(
|
||||
"Could not delete version audio %s; removing the row anyway", audio_path
|
||||
)
|
||||
db.delete(v)
|
||||
count += 1
|
||||
if count > 0:
|
||||
|
||||
Reference in New Issue
Block a user