Skip to content

Feature/#27 scheduler - #28

Open
wngjs8114 wants to merge 5 commits into
devfrom
feature/#27-scheduler
Open

Feature/#27 scheduler#28
wngjs8114 wants to merge 5 commits into
devfrom
feature/#27-scheduler

Conversation

@wngjs8114

Copy link
Copy Markdown
Collaborator

관련 이슈

Closes #27

작업 내용

확정된 StudyTask를 날짜별 AvailableTime에 자동 배치하고 DailyPlan/DailyPlanItem으로 저장

구조

  • allocate_tasks_to_days(): 순수 함수, DB 변경 없이 배치 결과만 계산
  • generate_schedule(): 배치 결과를 DB에 저장, transaction.atomic() + select_for_update()로 동시성 방지

배치 정책

  • 배치 시간: estimated_max_minutes 기준
  • 작업 분할 없음
  • 각 작업은 해당 과목 exam_date 이전 날짜에만 배치
  • 정렬: 시험일 → 중요도(high>medium>low) → order → id

저장 정책

  • 처리 순서: 배치 계산 → 미배치 검증(부분 저장 방지) → 기존 계획 처리 → 저장
  • replace_existing=False: 기존 계획 있으면 ScheduleAlreadyExistsError
  • replace_existing=True: 해당 exam_period의 기존 계획만 삭제 후 재생성 (다른 시험기간 영향 없음)
  • 같은 날짜 작업들은 하나의 DailyPlan 공유
  • 미배치 작업 있으면 UnallocatedTasksError, 아무 것도 저장 안 함

테스트

  • python manage.py test planner → 31개 통과

@wngjs8114

Copy link
Copy Markdown
Collaborator Author

피드백 반영했습니다:

  1. select_for_update() 관련: 로컬 SQLite는 row-level locking을 지원하지 않아 no-op으로 처리됩니다. 이 한계를 schedule_generator.py 모듈 docstring에 명시했습니다. 실제 동시성 검증은 운영 DB(PostgreSQL 등)에서 별도 통합 테스트가 필요할 것 같습니다.

  2. exam_period 불일치 방어 코드 추가했습니다 - MismatchedExamPeriodError, 관련 테스트(test_raises_when_task_belongs_to_other_exam_period)도 추가했습니다.

  3. feasibility_checker(A~B risky)와 scheduler(max 전용 배치) 정책 불일치는 코드 문제라기보다 정책 확인이 필요한 부분이라, 팀 회의 안건으로 올리겠습니다.

  4. 파일 분리했습니다 - scheduler.py는 순수 함수(allocate_tasks_to_days)만, schedule_generator.py는 DB 저장 로직(generate_schedule)으로 분리했습니다.

전체 32개 테스트 통과 확인했습니다. 확인 부탁드려요!

@6ye0m

6ye0m commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

정렬 기준에서 "CORE 우선"이 빠졌어요. 팀 확정 기준(11장) 원래는 "시험일 → 중요도 → CORE 작업 우선 → order/id" 4단계인데, 이 구현은 "시험일 → 중요도 → estimated_max_minutes 내림차순 → order/id"예요. depth(CORE/BASIC/OPTIONAL)가 정렬 기준에 아예 안 들어가있어요. 의도적으로 뺀 건지 확인이 필요해 보여요.
"작업 분할 없음" 정책이 명세서랑 달라요. 팀 문서엔 "하루 가능시간보다 큰 작업은 분할 허용"이라고 돼있는데, 이 PR은 분할을 아예 안 하고 못 들어가면 그냥 미배치 처리해요. MVP 단순화로 의도한 거면 괜찮은데, 명시적으로 합의된 건지 확인 필요해요.
(제일 중요) 나중에 #29(ProgressLog)랑 합쳐지면 데이터 유실 위험이 있어요. replace_existing=True로 재생성할 때 existing_items.delete()가 실행되는데, ProgressLog.daily_plan_item이 CASCADE라서, 이미 기록된 사용자의 학습 결과(완료/일부완료 기록)까지 스케줄 재생성 한 번에 같이 삭제돼요. 지금 이 브랜치엔 아직 ProgressLog가 없어서 이 PR만 보면 문제가 안 드러나지만, #29랑 합쳐지고 나서 "재생성" 기능을 쓰면 사용자가 입력한 공부 기록이 조용히 날아갈 수 있어요. 이건 머지 자체를 막을 문제는 아니고, 나중에 두 기능이 만날 때 반드시 처리해야 할 부분이라 지금 코멘트로 남겨두는 걸 추천해요.

@wngjs8114

Copy link
Copy Markdown
Collaborator Author

확인 감사합니다. 말씀해 주신 세 가지 기준을 PM 정책으로 확정하고 이번 커밋에 반영했습니다.

  1. 정렬 기준
    기존 팀 기준인 CORE 작업 우선을 유지했습니다.
    최종 정렬: 시험일 → 중요도(high>medium>low) → 깊이(core>basic>optional)
    → estimated_max_minutes 내림차순 → order → id
    TaskInput과 ORM 변환 과정에 depth를 추가했습니다.

  2. 작업 분할
    MVP에서는 스케줄러가 StudyTask를 분할하지 않는 것으로 확정했습니다.
    AI가 20~60분 단위로 작업을 생성하고, 스케줄러는 통째로 배치합니다.
    "분할 허용" 은 생각 안하면 됨.

  3. 기존 진행 기록 삭제 방지
    ProgressLog가 하나라도 존재하는 계획은 replace_existing=True여도
    전체 재생성을 거부하도록(ScheduleHasProgressError) 이번 커밋에 반영했고,
    관련 테스트도 추가했습니다. 학습 시작 이후 일정 변경은
    복구안 기능으로 처리하는 것으로 확정합니다.

전체 테스트 39개 통과 확인했습니다.

@wngjs8114

Copy link
Copy Markdown
Collaborator Author

추가 리뷰 사항 최종 반영했습니다.

  1. 작업 정렬 기준

기존 팀 정책인 CORE 작업 우선을 유지했습니다.

최종 정렬 순서는 다음과 같습니다.

시험일
→ 중요도(high > medium > low)
→ 깊이(core > basic > optional)
→ estimated_max_minutes 내림차순
→ order
→ id

이를 위해 TaskInput에 depth를 추가하고,
ORM 객체를 TaskInput으로 변환하는 과정에서도 실제 StudyTask.depth를
전달하도록 수정했습니다.

  1. 작업 분할 정책

MVP에서는 스케줄러가 StudyTask를 추가로 분할하지 않는 것으로
확정했습니다.

AI 분석 단계에서 작업별 기준 예상시간이 대략 20~60분이 되도록
StudyTask를 생성하고, 스케줄러는 생성된 작업을 하나의 단위로
통째로 배치합니다.

하루 가용시간에 들어갈 수 없는 작업은 분할하지 않고
unallocated_tasks로 반환합니다.

기존 문서의 하루 가능시간보다 큰 작업은 분할 허용 내용은
현재 MVP 정책인 작업 분할 없음으로 정정하겠습니다.

  1. 기존 진행 기록 삭제 방지

ProgressLog가 하나라도 존재하는 계획은 replace_existing=True여도
전체 재생성을 거부하도록 ScheduleHasProgressError를 추가했습니다.

DailyPlanItem 삭제 시 연결된 ProgressLog가 CASCADE로 삭제될 수 있으므로,
삭제 전에 진행 기록 존재 여부를 검사합니다.

학습 시작 이후의 일정 변경은 전체 재생성이 아니라
복구안 생성·적용 기능으로 처리하는 것으로 확정했습니다.

관련 테스트를 추가했으며 planner 테스트 39개 전체 통과 확인했습니다.
재검토 부탁드립니다.

@6ye0m

6ye0m commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator

git checkout feature/#27-scheduler
git merge origin/dev

혹시 충돌나면 task_extractor.py는 dev쪽(20~60분 규칙 있는 버전) 유지

git push origin feature/#27-scheduler

이 브랜치가 dev보다 뒤처져있어 불러오고 머지하면 될 듯 합니다!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[planner] 최초 계획 생성 (scheduler) 구현

2 participants