From dec9396d55dc01a15215c5c9639fc383999cdc80 Mon Sep 17 00:00:00 2001 From: jongjunn Date: Wed, 22 Jul 2026 21:49:24 +0900 Subject: [PATCH] fix(review): persist last_review + correct resolver enrollment key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 두 개의 프로덕션 버그 수정 (둘 다 infrastructure/repositories.py): 1. MySQLReviewCardRepository.save_card 가 last_review 를 저장하지 않아 review_card.last_review 가 항상 NULL 로 남았다. find_review_targets 의 멱등성 조건(rc.last_review IS NULL OR qs.submitted_at > rc.last_review)이 항상 참이 되어 야간 배치가 매 실행마다 전 카드를 재리뷰(당일 재리뷰로 처리 → FSRS stability 왜곡). 실측: 같은 날 재실행 시 skipped=0, updated=453. INSERT/UPDATE 에 last_review 추가. 2. MySQLEnrollmentQuizResolver.get_member_id 가 `enrollment WHERE id=%s` 로 조회했으나 enrollment 테이블 PK 는 enrollment_id 이고 id 컬럼은 없음 (V1__baseline.sql). "Unknown column 'id'" 로 유사문제 추천 경로 전체가 실패했다. WHERE enrollment_id=%s 로 수정. Co-Authored-By: Claude Opus 4.8 --- infrastructure/repositories.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/infrastructure/repositories.py b/infrastructure/repositories.py index 65836db..744ada5 100644 --- a/infrastructure/repositories.py +++ b/infrastructure/repositories.py @@ -317,14 +317,14 @@ def get_card(self, enrollment_id: str, lesson_id: str): def save_card(self, enrollment_id: str, lesson_id: str, card: Card) -> None: sql = """ - INSERT INTO review_card (enrollment_id, lesson_id, stability, difficulty, due, state) - VALUES (%s, %s, %s, %s, %s, %s) + INSERT INTO review_card (enrollment_id, lesson_id, stability, difficulty, due, last_review, state) + VALUES (%s, %s, %s, %s, %s, %s, %s) ON DUPLICATE KEY UPDATE stability = VALUES(stability), difficulty = VALUES(difficulty), - due = VALUES(due), state = VALUES(state) + due = VALUES(due), last_review = VALUES(last_review), state = VALUES(state) """ with get_connection() as conn, conn.cursor() as cur: - cur.execute(sql, (enrollment_id, lesson_id, card.stability, card.difficulty, card.due, str(card.state))) + cur.execute(sql, (enrollment_id, lesson_id, card.stability, card.difficulty, card.due, card.last_review, str(card.state))) class MySQLPendingReviewRepository: @@ -430,7 +430,7 @@ class MySQLEnrollmentQuizResolver: lesson↔quiz는 N:N(lesson_quiz_map)이라 '이 학생이 그 레슨 퀴즈 중 가장 최근 제출한 quiz'를 택함.""" def get_member_id(self, enrollment_id: str): - sql = "SELECT member_id FROM enrollment WHERE id = %s" + sql = "SELECT member_id FROM enrollment WHERE enrollment_id = %s" with get_connection() as conn, conn.cursor() as cur: cur.execute(sql, (enrollment_id,)) row = cur.fetchone()