Skip to content

fix(be): handle contest submissions without judgeable testcases - #3669

Open
dlwnsgk529 wants to merge 4 commits into
mainfrom
t2796-fix-sample-only-submission-judging-error
Open

fix(be): handle contest submissions without judgeable testcases#3669
dlwnsgk529 wants to merge 4 commits into
mainfrom
t2796-fix-sample-only-submission-judging-error

Conversation

@dlwnsgk529

@dlwnsgk529 dlwnsgk529 commented Jul 29, 2026

Copy link
Copy Markdown

Description

Evaluate with sample testcases included 옵션을 끈 대회에 샘플 테스트케이스만 존재하는 문제가 포함된 경우,
채점할 테스트케이스가 없어 제출이 Judging 상태에 계속 머무르는 문제를 수정합니다.

채점 대상 테스트케이스가 없는 대회 제출은 RabbitMQ 채점 요청을 발행하지 않고
기존 제출 결과 후속 처리 로직을 호출하여 Accepted 및 만점으로 확정합니다.
이후 문제 정답 통계와 대회 참가자 기록도 기존 정답 제출과 동일하게 갱신합니다.

구현한 내용은 다음과 같습니다.

  • 생성된 SubmissionResult 개수를 반환하도록 제출 결과 생성 로직을 변경
  • 히든 테스트케이스만 채점하는 대회에서 채점 대상이 0개인 경우를 분기 처리
  • 제출 결과와 점수를 각각 Accepted, 만점으로 한 번에 저장
  • 해당 분기에서는 불필요한 RabbitMQ 채점 요청 생략
  • 예외 처리 분기가 추후에 깨지는 것을 방지하기 위한 unit 테스트 추가

Additional context

현재 구현은 채점 대상 히든 테스트케이스가 없으면 코드를 실행하지 않고 제출을
Accepted 및 만점으로 처리합니다. 따라서 오답이나 컴파일되지 않는 코드도 정답으로
처리될 수 있습니다.

채점 대상이 없는 제출을 정답으로 간주하는 것이 적절한지 확인 부탁드립니다.

closes TAS-2796


Before submitting the PR, please make sure you do the following

채점 대상 테스트 케이스가 없는 경우 제출을 Accepted로 분기 처리한다.
SubmissionResult와 RabbitMQ 채점 요청을 생성하지 않아 Judging 상태로 남는 문제를 방지한다.
채점 대상 테스트케이스가 없는 대회 제출을 정답과 만점으로 확정한다.
RabbitMQ 채점 요청 없이 기존 문제 통계 및 대회 기록 후속 처리를 실행한다.
예외 처리 분기가 추후에 깨지는 것을 방지하기 위한 테스트를 추가한다.
@lshtar13

Copy link
Copy Markdown
Contributor

채점 대상이 없는 제출을 정답으로 간주하는 것이 적절한지 확인 부탁드립니다.

기획의 문제인 것 같은데, 개인적으로 정답으로 간주하는 것이 맞다고 생각합니다.
정답이 아닌 것으로 본다면 해당 문제는 정답을 제출할 경로가 없어집니다.
문제상황이 굉장히 희귀한 케이스이기 때문에 정하기 나름인 것 같습니다.
추가적으로, 문제 발생을 봉쇄하려면 UI 상에 안내문구("채점 대상이 없는 제출은 정답으로 간주합니다.")도 띄워주는 편이 낫다고 생각합니다.
그렇지만, 이 부분은 본 task의 범위를 넘어서기에 현재는 고려대상이 아닙니다.

@hjkim24

hjkim24 commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

리뷰 — fix(be): handle contest submissions without judgeable testcases

전반적으로 원인을 정확히 짚은 최소 변경이고, 테스트도 잘 붙어 있습니다. 구현 자체에는 정합성/회귀 이슈가 없어 보입니다. 아래는 확인한 내용과 논의가 필요한 지점입니다.

정합성 — 검증 완료

  • 순환 의존성 없음 / 기존 동작 회귀 없음. SubmissionSubscriptionServiceprisma/amqp/cache에만 의존하므로 SubmissionService에 주입해도 순환이 생기지 않습니다. 기존 프로덕션 호출부(submission-sub.service.ts:391)는 인자 하나만 넘기므로 새로 추가된 기본값 = false 로 그대로 동작합니다.
  • 빈 결과 확정 로직 정상. allAccepted = [].every(...) === trueAccepted. findUniquesubmissionResult.every.NOT Judging 필터도 빈 배열에서 vacuously true라 대상 row가 정상 조회됩니다.
  • updateSubmissionScore 건너뛰기는 최적화가 아니라 필수. calculateFractionalScore([])totalNumeratorSum === 0으로 0을 반환해서 만점 의도를 덮어써 버립니다. 따라서 score: PERCENTAGE_SCALE을 직접 세팅하는 방식이 맞습니다.
  • 랭킹도 만점 반영. updateContestRecord는 제출 점수가 아니라 contestProblem.score(문제 배점)를 사용하므로 대회 기록도 "만점"과 일관됩니다.

핵심 논의 지점 (PR 설명에서 이미 언급하신 부분)

코드를 실행하지 않으므로, 이 설정(히든 전용 채점 + 히든 테스트케이스 0개)의 대회 문제에는 오답/컴파일 실패/빈 제출을 포함한 모든 제출이 Accepted + 만점 + 대회 만점으로 기록됩니다. 즉 "영원히 Judging"이 "fail-open: 전원 만점"으로 바뀝니다.

  • 트리거 자체가 사실상 대회 misconfiguration(히든 전용인데 히든 테스트케이스가 없음)입니다. 조용히 전원 만점을 주는 것보다, 제출 생성 시점에 "채점 대상 테스트케이스가 없다"는 명확한 에러로 막거나 운영자에게 노출하는 쪽이 대회 무결성 관점에선 더 안전합니다.
  • 만약 auto-accept를 유지한다면, 순수 sample-only 케이스로만 한정하고 "테스트케이스가 아예 0개"인 경우는 별도로 경고/구분하는 것도 방법입니다.

→ "채점 대상 없는 제출을 만점 처리"가 의도된 정책인지 대회/기획 오너 확인이 머지 전 유일한 실질 블로커라고 봅니다. 조금이라도 애매하면 조용히 통과시키기보다 misconfiguration을 드러내는 쪽을 추천합니다.

사소한 제안

  • Boolean-trap 파라미터. updateSubmissionResult(submission.id, true)true가 호출부에서 의미가 안 드러납니다. 게다가 hasNoJudgeableTestcases는 (Accepted 강제 / 만점 강제 / 점수 재계산 생략) 3가지 동작을 겸합니다. 호출부가 하나뿐이라 지금은 괜찮지만, 이름을 더 명시적으로 하거나 옵션 객체로 받는 편이 낫습니다.
  • 조건 중복. testcasesCount === 0 && submission.contestId && judgeOnlyHiddenTestcases 에서 judgeOnlyHiddenTestcases는 대회 제출에서만 true(submission.service.ts:219가 유일한 출처)라 submission.contestId는 방어적 no-op입니다. 무해하지만 실제 가드는 judgeOnlyHiddenTestcases라는 점 참고용.
  • 문서 drift. createSubmission JSDoc 4번 단계가 여전히 "채점 요청 메시지 발행"만 설명하고 early-finalize 분기 언급이 없습니다. @param hasNoJudgeableTestcases도 "만점 강제 + 점수 재계산 생략" 동작을 함께 적어주면 좋겠습니다.
  • 재조회. updateSubmissionResultfindUniqueOrThrow 한 번 더 조회하는 건 드문 경로라 명확성 측면에서 수용 가능, 최적화 불필요.

테스트 — 양호

  • sub-service: update{ result: Accepted, score: 100 }로 호출되는지, updateSubmissionScore 미호출, updateProblemAccepted/updateContestRecord(…, true)로 호출되는지 검증 — good.
  • service: createSubmissionResults → 0일 때 updateSubmissionResult(id, true)로 확정하고 publish는 하지 않으며 확정된 row를 반환하는지 검증 — good.
  • (선택) 채점 대상 테스트케이스가 있는 대회 제출은 여전히 publish하고 early-finalize하지 않는다는 assertion(updateSubmissionResult 미호출)을 추가하면 분기를 양쪽에서 고정할 수 있습니다.

결론

버그 수정 자체는 정확·최소·테스트 완비로 문제없습니다. 머지 전 유일한 블로커는 코드가 아니라 정책 결정 — "채점 대상 없는 대회 제출을 조용히 Accepted+만점(fail-open) 처리"가 맞는지 확인입니다. 나머지는 nit입니다.

@hjkim24

hjkim24 commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

채점 대상이 없는 제출을 정답으로 간주하는 것이 적절한지 확인 부탁드립니다.

기획의 문제인 것 같은데, 개인적으로 정답으로 간주하는 것이 맞다고 생각합니다. 정답이 아닌 것으로 본다면 해당 문제는 정답을 제출할 경로가 없어집니다. 문제상황이 굉장히 희귀한 케이스이기 때문에 정하기 나름인 것 같습니다. 추가적으로, 문제 발생을 봉쇄하려면 UI 상에 안내문구("채점 대상이 없는 제출은 정답으로 간주합니다.")도 띄워주는 편이 낫다고 생각합니다. 그렇지만, 이 부분은 본 task의 범위를 넘어서기에 현재는 고려대상이 아닙니다.

저도 정답으로 간주하는 것이 맞다고 봅니다!

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants