mirror of
https://github.com/jamiepine/voicebox.git
synced 2026-10-04 01:25:18 -07:00
fix(profiles): commit the whole profile delete cascade once
delete_generations_by_profile (and the version sweep under it) committed on their own, so a failure between the generation sweep and the profile row left the profile listed with its history already gone. Both helpers take a commit flag now, and delete_profile passes commit=False so the single db.commit() at its end publishes the entire cascade. Other callers keep the default and are unchanged.
This commit is contained in:
committed by
capy-ai-staging[bot]
parent
012c957f4d
commit
f0f3802b79
@@ -18,7 +18,7 @@ from .. import config
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def _delete_generation_children(generation_id: str, db: Session) -> None:
|
def _delete_generation_children(generation_id: str, db: Session, commit: bool = True) -> None:
|
||||||
"""Remove the rows that reference a generation, plus any version audio files.
|
"""Remove the rows that reference a generation, plus any version audio files.
|
||||||
|
|
||||||
Story items and versions both point at the generation by a non-null FK.
|
Story items and versions both point at the generation by a non-null FK.
|
||||||
@@ -28,7 +28,7 @@ def _delete_generation_children(generation_id: str, db: Session) -> None:
|
|||||||
from . import versions as versions_mod
|
from . import versions as versions_mod
|
||||||
|
|
||||||
db.query(DBStoryItem).filter_by(generation_id=generation_id).delete()
|
db.query(DBStoryItem).filter_by(generation_id=generation_id).delete()
|
||||||
versions_mod.delete_versions_for_generation(generation_id, db)
|
versions_mod.delete_versions_for_generation(generation_id, db, commit=commit)
|
||||||
|
|
||||||
|
|
||||||
def _get_versions_for_generations(generation_ids: list[str], db: Session) -> dict:
|
def _get_versions_for_generations(generation_ids: list[str], db: Session) -> dict:
|
||||||
@@ -349,14 +349,18 @@ async def delete_failed_generations(db: Session) -> int:
|
|||||||
async def delete_generations_by_profile(
|
async def delete_generations_by_profile(
|
||||||
profile_id: str,
|
profile_id: str,
|
||||||
db: Session,
|
db: Session,
|
||||||
|
commit: bool = True,
|
||||||
) -> int:
|
) -> int:
|
||||||
"""
|
"""
|
||||||
Delete all generations for a profile.
|
Delete all generations for a profile.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
profile_id: Profile ID
|
profile_id: Profile ID
|
||||||
db: Database session
|
db: Database session
|
||||||
|
commit: Commit at the end. Pass False when the caller owns the
|
||||||
|
transaction (e.g. deleting the profile itself) so the whole
|
||||||
|
cascade lands in one commit.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Number of generations deleted
|
Number of generations deleted
|
||||||
"""
|
"""
|
||||||
@@ -365,7 +369,7 @@ async def delete_generations_by_profile(
|
|||||||
count = 0
|
count = 0
|
||||||
for generation in generations:
|
for generation in generations:
|
||||||
# Delete associated version files and rows first
|
# Delete associated version files and rows first
|
||||||
_delete_generation_children(generation.id, db)
|
_delete_generation_children(generation.id, db, commit=commit)
|
||||||
|
|
||||||
# Delete audio file
|
# Delete audio file
|
||||||
audio_path = config.resolve_storage_path(generation.audio_path)
|
audio_path = config.resolve_storage_path(generation.audio_path)
|
||||||
@@ -380,9 +384,10 @@ async def delete_generations_by_profile(
|
|||||||
# Delete from database
|
# Delete from database
|
||||||
db.delete(generation)
|
db.delete(generation)
|
||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
db.commit()
|
if commit:
|
||||||
|
db.commit()
|
||||||
|
|
||||||
return count
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -440,7 +440,7 @@ async def delete_profile(
|
|||||||
# Generations carry a non-null FK to the profile and the history query
|
# Generations carry a non-null FK to the profile and the history query
|
||||||
# inner-joins profiles, so anything left behind here becomes a row the UI
|
# inner-joins profiles, so anything left behind here becomes a row the UI
|
||||||
# can never show and a .wav in data/generations the user can never reclaim.
|
# can never show and a .wav in data/generations the user can never reclaim.
|
||||||
deleted_generations = await history.delete_generations_by_profile(profile_id, db)
|
deleted_generations = await history.delete_generations_by_profile(profile_id, db, commit=False)
|
||||||
if deleted_generations:
|
if deleted_generations:
|
||||||
logger.info("Deleted %d generations belonging to profile %s", deleted_generations, profile_id)
|
logger.info("Deleted %d generations belonging to profile %s", deleted_generations, profile_id)
|
||||||
|
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ def delete_version(version_id: str, db: Session) -> bool:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def delete_versions_for_generation(generation_id: str, db: Session) -> int:
|
def delete_versions_for_generation(generation_id: str, db: Session, commit: bool = True) -> 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
|
This runs as part of a wider cascade — deleting one generation, sweeping
|
||||||
@@ -196,6 +196,9 @@ def delete_versions_for_generation(generation_id: str, db: Session) -> int:
|
|||||||
strand the caller half-deleted, so the row goes regardless and the leaked
|
strand the caller half-deleted, so the row goes regardless and the leaked
|
||||||
file is logged. ``delete_version`` keeps raising, because a single
|
file is logged. ``delete_version`` keeps raising, because a single
|
||||||
user-initiated delete should fail loudly.
|
user-initiated delete should fail loudly.
|
||||||
|
|
||||||
|
Pass ``commit=False`` when the caller owns the transaction and will commit
|
||||||
|
the whole cascade itself.
|
||||||
"""
|
"""
|
||||||
versions = (
|
versions = (
|
||||||
db.query(DBGenerationVersion)
|
db.query(DBGenerationVersion)
|
||||||
@@ -214,7 +217,7 @@ def delete_versions_for_generation(generation_id: str, db: Session) -> int:
|
|||||||
)
|
)
|
||||||
db.delete(v)
|
db.delete(v)
|
||||||
count += 1
|
count += 1
|
||||||
if count > 0:
|
if count > 0 and commit:
|
||||||
db.commit()
|
db.commit()
|
||||||
return count
|
return count
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user