o2o-castad-backend/app/archive/worker/archive_task.py

186 lines
6.8 KiB
Python

"""
Archive Worker 모듈
아카이브 관련 백그라운드 작업을 처리합니다.
- 소프트 삭제 (is_deleted=True 설정)
"""
from sqlalchemy import func, select, update
from app.database.session import BackgroundSessionLocal
from app.home.models import Image, Project
from app.lyric.models import Lyric
from app.song.models import Song, SongTimestamp
from app.utils.logger import get_logger
from app.video.models import Video
logger = get_logger(__name__)
async def soft_delete_by_task_id(task_id: str) -> dict:
"""
task_id에 해당하는 모든 관련 데이터를 소프트 삭제합니다.
대상 테이블 (refresh_token, social_account, user 제외):
- Project
- Image
- Lyric
- Song
- SongTimestamp (suno_audio_id 기준)
- Video
Args:
task_id: 삭제할 프로젝트의 task_id
Returns:
dict: 각 테이블별 업데이트된 레코드 수
"""
logger.info(f"[soft_delete_by_task_id] START - task_id: {task_id}")
logger.debug(f"[soft_delete_by_task_id] DEBUG - 백그라운드 태스크 시작")
result = {
"task_id": task_id,
"project": 0,
"image": 0,
"lyric": 0,
"song": 0,
"song_timestamp": 0,
"video": 0,
}
try:
async with BackgroundSessionLocal() as session:
# DEBUG: 삭제 전 각 테이블의 데이터 수 확인
video_before = await session.execute(
select(func.count(Video.id)).where(
Video.task_id == task_id, Video.is_deleted == False
)
)
logger.debug(
f"[soft_delete_by_task_id] DEBUG - 삭제 전 Video 수: {video_before.scalar() or 0}"
)
song_before = await session.execute(
select(func.count(Song.id)).where(
Song.task_id == task_id, Song.is_deleted == False
)
)
logger.debug(
f"[soft_delete_by_task_id] DEBUG - 삭제 전 Song 수: {song_before.scalar() or 0}"
)
lyric_before = await session.execute(
select(func.count(Lyric.id)).where(
Lyric.task_id == task_id, Lyric.is_deleted == False
)
)
logger.debug(
f"[soft_delete_by_task_id] DEBUG - 삭제 전 Lyric 수: {lyric_before.scalar() or 0}"
)
image_before = await session.execute(
select(func.count(Image.id)).where(
Image.task_id == task_id, Image.is_deleted == False
)
)
logger.debug(
f"[soft_delete_by_task_id] DEBUG - 삭제 전 Image 수: {image_before.scalar() or 0}"
)
project_before = await session.execute(
select(func.count(Project.id)).where(
Project.task_id == task_id, Project.is_deleted == False
)
)
logger.debug(
f"[soft_delete_by_task_id] DEBUG - 삭제 전 Project 수: {project_before.scalar() or 0}"
)
# 1. Video 소프트 삭제
video_stmt = (
update(Video)
.where(Video.task_id == task_id, Video.is_deleted == False)
.values(is_deleted=True)
)
video_result = await session.execute(video_stmt)
result["video"] = video_result.rowcount
logger.info(f"[soft_delete_by_task_id] Video soft deleted - count: {result['video']}")
logger.debug(f"[soft_delete_by_task_id] DEBUG - Video rowcount: {video_result.rowcount}")
# 2. SongTimestamp 소프트 삭제 (Song의 suno_audio_id 기준, 서브쿼리 사용)
suno_subquery = (
select(Song.suno_audio_id)
.where(
Song.task_id == task_id,
Song.suno_audio_id.isnot(None),
)
.scalar_subquery()
)
timestamp_stmt = (
update(SongTimestamp)
.where(
SongTimestamp.suno_audio_id.in_(suno_subquery),
SongTimestamp.is_deleted == False,
)
.values(is_deleted=True)
)
timestamp_result = await session.execute(timestamp_stmt)
result["song_timestamp"] = timestamp_result.rowcount
logger.info(
f"[soft_delete_by_task_id] SongTimestamp soft deleted - count: {result['song_timestamp']}"
)
# 3. Song 소프트 삭제
song_stmt = (
update(Song)
.where(Song.task_id == task_id, Song.is_deleted == False)
.values(is_deleted=True)
)
song_result = await session.execute(song_stmt)
result["song"] = song_result.rowcount
logger.info(f"[soft_delete_by_task_id] Song soft deleted - count: {result['song']}")
# 4. Lyric 소프트 삭제
lyric_stmt = (
update(Lyric)
.where(Lyric.task_id == task_id, Lyric.is_deleted == False)
.values(is_deleted=True)
)
lyric_result = await session.execute(lyric_stmt)
result["lyric"] = lyric_result.rowcount
logger.info(f"[soft_delete_by_task_id] Lyric soft deleted - count: {result['lyric']}")
# 5. Image 소프트 삭제
image_stmt = (
update(Image)
.where(Image.task_id == task_id, Image.is_deleted == False)
.values(is_deleted=True)
)
image_result = await session.execute(image_stmt)
result["image"] = image_result.rowcount
logger.info(f"[soft_delete_by_task_id] Image soft deleted - count: {result['image']}")
# 6. Project 소프트 삭제
project_stmt = (
update(Project)
.where(Project.task_id == task_id, Project.is_deleted == False)
.values(is_deleted=True)
)
project_result = await session.execute(project_stmt)
result["project"] = project_result.rowcount
logger.info(f"[soft_delete_by_task_id] Project soft deleted - count: {result['project']}")
await session.commit()
logger.info(
f"[soft_delete_by_task_id] SUCCESS - task_id: {task_id}, "
f"deleted: project={result['project']}, image={result['image']}, "
f"lyric={result['lyric']}, song={result['song']}, "
f"song_timestamp={result['song_timestamp']}, video={result['video']}"
)
return result
except Exception as e:
logger.error(f"[soft_delete_by_task_id] EXCEPTION - task_id: {task_id}, error: {e}", exc_info=True)
raise