186 lines
6.8 KiB
Python
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
|