youtube bug fix, timezone 수정, lazyloading 수정 .

get_video
hbyang 2026-02-09 13:15:20 +09:00
parent 40afe9392c
commit e29e10eb29
3 changed files with 22 additions and 16 deletions

View File

@ -4,6 +4,7 @@ Social Account Service
소셜 계정 연동 관련 비즈니스 로직을 처리합니다.
"""
import json
import logging
import secrets
from datetime import timedelta
@ -27,10 +28,8 @@ redis_client = Redis(
decode_responses=True,
)
from app.social.exceptions import (
InvalidStateError,
OAuthStateExpiredError,
OAuthTokenRefreshError,
SocialAccountAlreadyConnectedError,
SocialAccountNotFoundError,
TokenExpiredError,
)
@ -90,7 +89,7 @@ class SocialAccountService:
await redis_client.setex(
state_key,
social_oauth_settings.OAUTH_STATE_TTL_SECONDS,
str(state_data),
json.dumps(state_data), # JSON으로 직렬화
)
logger.debug(f"[SOCIAL] OAuth state 저장 - key: {state_key}")
@ -126,9 +125,7 @@ class SocialAccountService:
SocialAccountResponse: 연동된 소셜 계정 정보
Raises:
InvalidStateError: state 토큰이 유효하지 않은 경우
OAuthStateExpiredError: state 토큰이 만료된 경우
SocialAccountAlreadyConnectedError: 이미 연동된 계정인 경우
OAuthStateExpiredError: state 토큰이 만료되거나 유효하지 않은 경우
"""
logger.info(f"[SOCIAL] OAuth 콜백 처리 시작 - state: {state[:20]}...")
@ -140,8 +137,8 @@ class SocialAccountService:
logger.warning(f"[SOCIAL] state 토큰 없음 또는 만료 - state: {state[:20]}...")
raise OAuthStateExpiredError()
# state 데이터 파싱
state_data = eval(state_data_str) # {"user_uuid": "...", "platform": "..."}
# state 데이터 파싱 (JSON 역직렬화)
state_data = json.loads(state_data_str)
user_uuid = state_data["user_uuid"]
platform = SocialPlatform(state_data["platform"])
@ -307,7 +304,9 @@ class SocialAccountService:
if account.token_expires_at is None:
should_refresh = True
else:
buffer_time = now() + timedelta(hours=1)
# DB datetime은 naive, now()는 aware이므로 naive로 통일하여 비교
current_time = now().replace(tzinfo=None)
buffer_time = current_time + timedelta(hours=1)
if account.token_expires_at <= buffer_time:
should_refresh = True
@ -514,7 +513,9 @@ class SocialAccountService:
)
should_refresh = True
else:
buffer_time = now() + timedelta(minutes=10)
# DB datetime은 naive, now()는 aware이므로 naive로 통일하여 비교
current_time = now().replace(tzinfo=None)
buffer_time = current_time + timedelta(minutes=10)
if account.token_expires_at <= buffer_time:
logger.info(
f"[SOCIAL] 토큰 만료 임박, 갱신 시작 - account_id: {account.id}"
@ -573,11 +574,13 @@ class SocialAccountService:
if token_response.refresh_token:
account.refresh_token = token_response.refresh_token
if token_response.expires_in:
account.token_expires_at = now() + timedelta(
# DB에 naive datetime으로 저장 (MySQL DateTime은 timezone 미지원)
account.token_expires_at = now().replace(tzinfo=None) + timedelta(
seconds=token_response.expires_in
)
await session.commit()
await session.refresh(account)
logger.info(f"[SOCIAL] 토큰 갱신 완료 - account_id: {account.id}")
return account.access_token
@ -631,10 +634,10 @@ class SocialAccountService:
Returns:
SocialAccount: 생성된 소셜 계정
"""
# 토큰 만료 시간 계산
# 토큰 만료 시간 계산 (DB에 naive datetime으로 저장)
token_expires_at = None
if token_response.expires_in:
token_expires_at = now() + timedelta(
token_expires_at = now().replace(tzinfo=None) + timedelta(
seconds=token_response.expires_in
)
@ -687,7 +690,8 @@ class SocialAccountService:
if token_response.refresh_token:
account.refresh_token = token_response.refresh_token
if token_response.expires_in:
account.token_expires_at = now() + timedelta(
# DB에 naive datetime으로 저장
account.token_expires_at = now().replace(tzinfo=None) + timedelta(
seconds=token_response.expires_in
)
if token_response.scope:
@ -703,7 +707,7 @@ class SocialAccountService:
# 재연결 시 연결 시간 업데이트
if update_connected_at:
account.connected_at = now()
account.connected_at = now().replace(tzinfo=None)
await session.commit()
await session.refresh(account)

View File

@ -71,7 +71,7 @@ async def _update_upload_status(
if error_message:
upload.error_message = error_message
if status == UploadStatus.COMPLETED:
upload.uploaded_at = now()
upload.uploaded_at = now().replace(tzinfo=None)
await session.commit()
logger.info(

View File

@ -391,6 +391,7 @@ class RefreshToken(Base):
user: Mapped["User"] = relationship(
"User",
back_populates="refresh_tokens",
lazy="selectin", # lazy loading 방지
)
def __repr__(self) -> str:
@ -591,6 +592,7 @@ class SocialAccount(Base):
user: Mapped["User"] = relationship(
"User",
back_populates="social_accounts",
lazy="selectin", # lazy loading 방지
)
def __repr__(self) -> str: