diff --git a/app/song/api/routers/v1/song.py b/app/song/api/routers/v1/song.py index 3f2a07b..5b8330a 100644 --- a/app/song/api/routers/v1/song.py +++ b/app/song/api/routers/v1/song.py @@ -415,13 +415,6 @@ async def get_song_status( # processing 상태인 경우에만 백그라운드 태스크 실행 (중복 방지) if song and song.status == "processing": - # store_name 조회 - project_result = await session.execute( - select(Project).where(Project.id == song.project_id) - ) - project = project_result.scalar_one_or_none() - store_name = project.store_name if project else "song" - # 상태를 uploading으로 변경 (중복 호출 방지) song.status = "uploading" song.suno_audio_id = first_clip.get("id") @@ -435,12 +428,11 @@ async def get_song_status( download_and_upload_song_by_suno_task_id, suno_task_id=song_id, audio_url=audio_url, - store_name=store_name, user_uuid=current_user.user_uuid, duration=clip_duration, ) logger.info( - f"[get_song_status] Background task scheduled - song_id: {suno_task_id}, store_name: {store_name}" + f"[get_song_status] Background task scheduled - song_id: {suno_task_id}" ) suno_audio_id = first_clip.get("id") diff --git a/app/song/worker/song_task.py b/app/song/worker/song_task.py index f743669..2cebb3b 100644 --- a/app/song/worker/song_task.py +++ b/app/song/worker/song_task.py @@ -4,8 +4,6 @@ Song Background Tasks 노래 생성 관련 백그라운드 태스크를 정의합니다. """ -import traceback -from datetime import date from pathlib import Path import aiofiles @@ -15,10 +13,8 @@ from sqlalchemy.exc import SQLAlchemyError from app.database.session import BackgroundSessionLocal from app.song.models import Song -from app.utils.common import generate_task_id from app.utils.logger import get_logger from app.utils.upload_blob_as_request import AzureBlobUploader -from config import prj_settings # 로거 설정 logger = get_logger("song") @@ -109,87 +105,23 @@ async def _download_audio(url: str, task_id: str) -> bytes: return response.content -async def download_and_save_song( - task_id: str, - audio_url: str, - store_name: str, -) -> None: - """백그라운드에서 노래를 다운로드하고 Song 테이블을 업데이트합니다. - - Args: - task_id: 프로젝트 task_id - audio_url: 다운로드할 오디오 URL - store_name: 저장할 파일명에 사용할 업체명 - """ - logger.info(f"[download_and_save_song] START - task_id: {task_id}, store_name: {store_name}") - - try: - # 저장 경로 생성: media/song/{날짜}/{uuid7}/{store_name}.mp3 - today = date.today().strftime("%Y-%m-%d") - unique_id = await generate_task_id() - # 파일명에 사용할 수 없는 문자 제거 - safe_store_name = "".join( - c for c in store_name if c.isalnum() or c in (" ", "_", "-") - ).strip() - safe_store_name = safe_store_name or "song" - file_name = f"{safe_store_name}.mp3" - - # 절대 경로 생성 - media_dir = Path("media") / "song" / today / unique_id - media_dir.mkdir(parents=True, exist_ok=True) - file_path = media_dir / file_name - logger.info(f"[download_and_save_song] Directory created - path: {file_path}") - - # 오디오 파일 다운로드 - logger.info(f"[download_and_save_song] Downloading audio - task_id: {task_id}, url: {audio_url}") - - content = await _download_audio(audio_url, task_id) - - async with aiofiles.open(str(file_path), "wb") as f: - await f.write(content) - - logger.info(f"[download_and_save_song] File saved - task_id: {task_id}, path: {file_path}") - - # 프론트엔드에서 접근 가능한 URL 생성 - relative_path = f"/media/song/{today}/{unique_id}/{file_name}" - base_url = f"{prj_settings.PROJECT_DOMAIN}" - file_url = f"{base_url}{relative_path}" - logger.info(f"[download_and_save_song] URL generated - task_id: {task_id}, url: {file_url}") - - # Song 테이블 업데이트 - await _update_song_status(task_id, "completed", file_url) - logger.info(f"[download_and_save_song] SUCCESS - task_id: {task_id}") - - except httpx.HTTPError as e: - logger.error(f"[download_and_save_song] DOWNLOAD ERROR - task_id: {task_id}, error: {e}", exc_info=True) - await _update_song_status(task_id, "failed") - - except SQLAlchemyError as e: - logger.error(f"[download_and_save_song] DB ERROR - task_id: {task_id}, error: {e}", exc_info=True) - await _update_song_status(task_id, "failed") - - except Exception as e: - logger.error(f"[download_and_save_song] EXCEPTION - task_id: {task_id}, error: {e}", exc_info=True) - await _update_song_status(task_id, "failed") - - async def download_and_upload_song_by_suno_task_id( suno_task_id: str, audio_url: str, - store_name: str, user_uuid: str, duration: float | None = None, ) -> None: """suno_task_id로 Song을 조회하여 노래를 다운로드하고 Azure Blob Storage에 업로드한 뒤 Song 테이블을 업데이트합니다. + 파일명은 suno_task_id를 사용하여 고유성을 보장합니다. + Args: - suno_task_id: Suno API 작업 ID + suno_task_id: Suno API 작업 ID (파일명으로도 사용) audio_url: 다운로드할 오디오 URL - store_name: 저장할 파일명에 사용할 업체명 user_uuid: 사용자 UUID (Azure Blob Storage 경로에 사용) duration: 노래 재생 시간 (초) """ - logger.info(f"[download_and_upload_song_by_suno_task_id] START - suno_task_id: {suno_task_id}, store_name: {store_name}, duration: {duration}") + logger.info(f"[download_and_upload_song_by_suno_task_id] START - suno_task_id: {suno_task_id}, duration: {duration}") temp_file_path: Path | None = None task_id: str | None = None @@ -211,12 +143,8 @@ async def download_and_upload_song_by_suno_task_id( task_id = song.task_id logger.info(f"[download_and_upload_song_by_suno_task_id] Song found - suno_task_id: {suno_task_id}, task_id: {task_id}") - # 파일명에 사용할 수 없는 문자 제거 - safe_store_name = "".join( - c for c in store_name if c.isalnum() or c in (" ", "_", "-") - ).strip() - safe_store_name = safe_store_name or "song" - file_name = f"{safe_store_name}.mp3" + # suno_task_id를 파일명으로 사용 (고유 ID이므로 sanitize 불필요) + file_name = f"{suno_task_id}.mp3" # 임시 저장 경로 생성 temp_dir = Path("media") / "temp" / task_id