feat(session): 시간초과 세션 자동 종료 (좀비 세션 방지)#124
Merged
Merged
Conversation
면접을 중간에 버리면(자기소개 미답변·STT 실패·탭 종료) 세션이 IN_PROGRESS 로 영원히 남아 피드백도 못 받고 히스토리·중복회피를 오염시키던 갭을 해소. - @EnableScheduling(SchedulingConfig) + SessionTimeoutSweeper(@scheduled 5분 주기)가 maxDurationMinutes 초과한 IN_PROGRESS 세션을 찾아 SessionTimeoutService.endTimedOut 호출. 진행 세션은 소수라 전체 조회 후 메모리 필터(startedAt + maxDurationMinutes). - SessionTimeoutService: 답변 있으면 COMPLETED(→ SessionEndedEvent(DURATION_EXCEEDED) → 피드백 생성), 없으면 INTERRUPTED(피드백 없음). IN_PROGRESS 재확인으로 멀티 인스턴스 안전. - repo: findByStatusAndDeletedFalse, existsBySession_IdAndRole 추가. - 주기 설정: interview.session.sweep-interval-ms(기본 300000)·sweep-initial-delay-ms(기본 60000). - 테스트(서비스 분기 + 스위퍼 필터) + CLAUDE 갱신. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
i3months
added a commit
that referenced
this pull request
Jun 28, 2026
…-hardening fix(session): 세션 종료 동시성 하드닝 (#124 후속)
i3months
added a commit
to i3months/stackup
that referenced
this pull request
Jun 30, 2026
회의적 멀티에이전트 리뷰(3/3 검증)에서 발견한 Team-StackUp#124 스위퍼 동시성 결함 3건. 1) [HIGH] 종료 세션 사후 변조: QuestionsCallbackService.apply()가 status 미확인 → 스위퍼/수동 종료 뒤 늦게 도착한 POOL/FOLLOWUP 콜백이 종료 세션에 질문·placeholder INSERT. apply()에 isTerminal() 가드 추가(멱등 마킹 후 드롭). 2) [MEDIUM] generate.feedback 이중 발행: 락 없는 COMPLETED 전이로 동시 종료 시 SessionEndedEvent 가 두 번 발행(멱등 가드가 비동기 생성 피드백 행에 의존해 무력화). 3) [MEDIUM] 막판 답변 발화가 종료 세션에 꼬리질문 누적. 수정: - InterviewSessionRepository.finishIfInProgress: 조건부 UPDATE(WHERE status=IN_PROGRESS)로 종료 전이를 원자화. 영향 행 1인 트랜잭션만 종료 부수효과 발행 → DB 행 락 직렬화로 동시 종료(스위퍼·수동·콜백) 시 정확히 한 번만 SessionEndedEvent 발행. - SessionTimeoutService/SessionService.end/QuestionsCallbackService.endSession 모두 finishIfInProgress 게이트 사용. - SessionFollowupRequester.onAnswerSubmitted 에 isTerminal() 가드. - SessionStatus.isTerminal() 헬퍼 추가. - 테스트: 종료 경쟁 패배(lost-race) 미발행 검증 추가, 기존 종료 테스트 보강. 전체 통과. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
변경 사항
스켑틱 리뷰에서 가장 큰 남은 갭이었던 세션 좀비화를 해소합니다.
이제
@Scheduled스위퍼가 시간 초과된 진행 중 세션을 자동 종료합니다.동작
SchedulingConfig(@EnableScheduling) +SessionTimeoutSweeper(@Scheduled, 기본 5분 주기):maxDurationMinutes(세션별, startedAt 기준) 초과한IN_PROGRESS세션을 찾아SessionTimeoutService.endTimedOut(id)호출. 진행 세션은 소수라 전체 조회 후 메모리 필터.SessionTimeoutService(세션마다 독립 트랜잭션):COMPLETED+SessionEndedEvent(DURATION_EXCEEDED)→ 피드백 생성INTERRUPTED(피드백 없음, 정리만)IN_PROGRESS재확인 → 멀티 인스턴스 중복 실행에도 안전(+ 피드백 멱등)findByStatusAndDeletedFalse,existsBySession_IdAndRole추가interview.session.sweep-interval-ms(기본 300000) ·sweep-initial-delay-ms(기본 60000)테스트
SessionTimeoutServiceTest: 답변O→COMPLETED+EndedEvent / 답변X→INTERRUPTED+EndedEvent 미발행 / 이미 종료→no-opSessionTimeoutSweeperTest: 시간초과 세션만 종료, 신규 세션은 제외비고
시간 기준은
maxDurationMinutes(기본 60분) — 버려진 세션은 최대 그 시간 내 정리됩니다. 더 빠른 유휴(idle) 기반 정리는 마지막 메시지 시각 추적이 필요해 후속으로 둡니다.🤖 Generated with Claude Code