o2o-castad-backend/app/lyric/worker/lyric_task.py

138 lines
5.6 KiB
Python

"""
Lyric Background Tasks
가사 생성 관련 백그라운드 태스크를 정의합니다.
"""
import traceback
from sqlalchemy import select
from sqlalchemy.exc import SQLAlchemyError
from app.database.session import BackgroundSessionLocal
from app.lyric.models import Lyric
from app.utils.chatgpt_prompt import ChatgptService
from app.utils.logger import get_logger
# 로거 설정
logger = get_logger("lyric")
async def _update_lyric_status(
task_id: str,
status: str,
result: str | None = None,
) -> bool:
"""Lyric 테이블의 상태를 업데이트합니다.
Args:
task_id: 프로젝트 task_id
status: 변경할 상태 ("processing", "completed", "failed")
result: 가사 결과 또는 에러 메시지
Returns:
bool: 업데이트 성공 여부
"""
try:
async with BackgroundSessionLocal() as session:
query_result = await session.execute(
select(Lyric)
.where(Lyric.task_id == task_id)
.order_by(Lyric.created_at.desc())
.limit(1)
)
lyric = query_result.scalar_one_or_none()
if lyric:
lyric.status = status
if result is not None:
lyric.lyric_result = result
await session.commit()
logger.info(f"[Lyric] Status updated - task_id: {task_id}, status: {status}")
return True
else:
logger.warning(f"[Lyric] NOT FOUND in DB - task_id: {task_id}")
return False
except SQLAlchemyError as e:
logger.error(f"[Lyric] DB Error while updating status - task_id: {task_id}, error: {e}")
return False
except Exception as e:
logger.error(f"[Lyric] Unexpected error while updating status - task_id: {task_id}, error: {e}")
return False
async def generate_lyric_background(
task_id: str,
prompt: str,
language: str,
) -> None:
"""백그라운드에서 ChatGPT를 통해 가사를 생성하고 Lyric 테이블을 업데이트합니다.
Args:
task_id: 프로젝트 task_id
prompt: ChatGPT에 전달할 프롬프트
language: 가사 언어
"""
import time
task_start = time.perf_counter()
logger.info(f"[generate_lyric_background] START - task_id: {task_id}")
logger.debug(f"[generate_lyric_background] ========== START ==========")
logger.debug(f"[generate_lyric_background] task_id: {task_id}")
logger.debug(f"[generate_lyric_background] language: {language}")
logger.debug(f"[generate_lyric_background] prompt length: {len(prompt)}")
try:
# ========== Step 1: ChatGPT 서비스 초기화 ==========
step1_start = time.perf_counter()
logger.debug(f"[generate_lyric_background] Step 1: ChatGPT 서비스 초기화...")
service = ChatgptService(
customer_name="", # 프롬프트가 이미 생성되었으므로 빈 값
region="",
detail_region_info="",
language=language,
)
step1_elapsed = (time.perf_counter() - step1_start) * 1000
logger.debug(f"[generate_lyric_background] Step 1 완료 ({step1_elapsed:.1f}ms)")
# ========== Step 2: ChatGPT API 호출 (가사 생성) ==========
step2_start = time.perf_counter()
logger.info(f"[generate_lyric_background] Step 2: ChatGPT API 호출 시작 - task_id: {task_id}")
logger.debug(f"[generate_lyric_background] Step 2: ChatGPT API 호출 시작...")
result = await service.generate(prompt=prompt)
step2_elapsed = (time.perf_counter() - step2_start) * 1000
logger.info(f"[generate_lyric_background] Step 2 완료 - 응답 {len(result)}자 ({step2_elapsed:.1f}ms)")
# ========== Step 3: DB 상태 업데이트 ==========
step3_start = time.perf_counter()
logger.debug(f"[generate_lyric_background] Step 3: DB 상태 업데이트...")
await _update_lyric_status(task_id, "completed", result)
step3_elapsed = (time.perf_counter() - step3_start) * 1000
logger.debug(f"[generate_lyric_background] Step 3 완료 ({step3_elapsed:.1f}ms)")
# ========== 완료 ==========
total_elapsed = (time.perf_counter() - task_start) * 1000
logger.info(f"[generate_lyric_background] SUCCESS - task_id: {task_id}, 총 소요시간: {total_elapsed:.1f}ms")
logger.debug(f"[generate_lyric_background] ========== SUCCESS ==========")
logger.debug(f"[generate_lyric_background] 총 소요시간: {total_elapsed:.1f}ms")
logger.debug(f"[generate_lyric_background] - Step 1 (서비스 초기화): {step1_elapsed:.1f}ms")
logger.debug(f"[generate_lyric_background] - Step 2 (GPT API 호출): {step2_elapsed:.1f}ms")
logger.debug(f"[generate_lyric_background] - Step 3 (DB 업데이트): {step3_elapsed:.1f}ms")
except SQLAlchemyError as e:
elapsed = (time.perf_counter() - task_start) * 1000
logger.error(f"[generate_lyric_background] DB ERROR - task_id: {task_id}, error: {e} ({elapsed:.1f}ms)", exc_info=True)
await _update_lyric_status(task_id, "failed", f"Database Error: {str(e)}")
except Exception as e:
elapsed = (time.perf_counter() - task_start) * 1000
logger.error(f"[generate_lyric_background] EXCEPTION - task_id: {task_id}, error: {e} ({elapsed:.1f}ms)", exc_info=True)
await _update_lyric_status(task_id, "failed", f"Error: {str(e)}")