Skip to content

Commit

Permalink
유저 API N+1 쿼리 개선 (#27)
Browse files Browse the repository at this point in the history
- Session 생성 시 간헐적으로 DB 와 통신에 실패하는 케이스를 대응하기 위해 retry 로직 추가
- 각 retry 마다 비동기적으로 대기하는 로직을 위해 get_db_session 을 async generator 로 변경
- UserRepository 의 get_users 에서 N+1 쿼리가 발생하는 문제를 개선
  • Loading branch information
minkyu97 committed Jul 6, 2024
1 parent 724f9f3 commit e5b1e05
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 8 deletions.
4 changes: 2 additions & 2 deletions waffledotcom/src/apps/user/repositories.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from fastapi import Depends
from sqlalchemy.orm import Session
from sqlalchemy.orm import Session, joinedload

from waffledotcom.src.apps.user.models import User
from waffledotcom.src.database.connection import Transaction, get_db_session
Expand All @@ -15,7 +15,7 @@ def __init__(
self.transaction = transaction

def get_users(self) -> list[User]:
return self.session.query(User).all()
return self.session.query(User).options(joinedload(User.positions)).all()

def get_user_by_id(self, user_id: int) -> User | None:
return self.session.query(User).filter(User.id == user_id).first()
Expand Down
21 changes: 15 additions & 6 deletions waffledotcom/src/database/connection.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from typing import Iterator
import asyncio
from collections.abc import AsyncIterator

import sqlalchemy
from fastapi import Depends
from sqlalchemy import orm
from sqlalchemy.exc import DatabaseError
from sqlalchemy.orm.session import Session

from waffledotcom.src.database.config import db_config
Expand All @@ -22,17 +24,24 @@ def __init__(self):
def get_engine(self) -> sqlalchemy.Engine:
return self._engine

def make_session(self) -> orm.Session:
session = self._session_maker()
return session
async def make_session(self) -> orm.Session:
exc = RuntimeError("이게 실행되면 버그이다.")
for _ in range(5):
try:
session = self._session_maker()
return session
except DatabaseError as e:
exc = e
await asyncio.sleep(1)
raise exc

def teardown(self):
orm.close_all_sessions()
self._engine.dispose()


def get_db_session() -> Iterator[orm.Session]:
session = DBSessionFactory().make_session()
async def get_db_session() -> AsyncIterator[orm.Session]:
session = await DBSessionFactory().make_session()

try:
yield session
Expand Down

0 comments on commit e5b1e05

Please sign in to comment.