커밋-리스트 API의 “DB 우선 조회”가 돌아가는 정확한 메커니즘

bash

overview/views.py
└─ commit_list_api(request)

1. 실행 흐름 한눈에 보기

python

owner   = request.GET['owner']
repo    = request.GET['repo']
username= request.GET.get('username')
count   = int(request.GET.get('count', 20))

db_commits = get_stored_commits(owner, repo, username, count)

if not db_commits:                          # ❶ DB에 없으면
    raw_commits = fetch_detailed_commit_history(   # ❷ GitHub GraphQL 호출
                      owner, repo, username, count)
    return JsonResponse({'commits': raw_commits})
else:                                       # ❸ DB에 있으면
    serialized = _serialize(db_commits)     # ❹ Django → GitHub 형식 변환
    return JsonResponse({'commits': serialized})


2. ❶ get_stored_commits() 내부 원리 (utils.py)

python

def get_stored_commits(owner, repo, username=None, count=20):
    # (1) Repository FK 찾기
    repository = Repository.objects.get(owner=owner, name=repo)

    # (2) Commit 테이블 필터링
    qs = Commit.objects.filter(repository=repository)
    if username:
        qs = qs.filter(author=username)

    # (3) 최신순 정렬 + 슬라이싱
    return qs.order_by('-committed_date')[:count]

단계 SQL로 번역하면 비고
(1) SELECT id FROM overview_repository WHERE owner=… AND name=… 없으면 DoesNotExist 예외 → 상위에서 except Repository.DoesNotExist: 처리
(2) SELECT * FROM overview_commit WHERE repository_id=X [AND author='username']
(3) … ORDER BY committed_date DESC LIMIT <count> 최신 커밋 n개

성공 조건 : 위 쿼리 결과가 하나라도 있으면 “캐시 Hit”.


3. ❷ fetch_detailed_commit_history() 로 GitHub 재조회

즉 첫 캐시 Miss 시 네트워크를 타면서 동시에 DB 캐싱을 끝냅니다.


4. ❸ DB Hit 분기에서 직렬화(_serialize)

python

commit_dict = {
    'oid'          : commit.sha,
    'author'       : {
        'name' : commit.author,
        'user' : {'login': commit.author}
    },
    'message'      : commit.message,
    'committedDate': commit.committed_date.isoformat(),
    'additions'    : commit.additions,
    'deletions'    : commit.deletions,
    'changedFiles' : commit.changed_files
}