Skip to content

[✨Feat] 최초 첨삭 비동기 worker 구현#49

Merged
yong203 merged 1 commit into
devfrom
feat/#48
Jun 28, 2026
Merged

[✨Feat] 최초 첨삭 비동기 worker 구현#49
yong203 merged 1 commit into
devfrom
feat/#48

Conversation

@yong203

@yong203 yong203 commented Jun 28, 2026

Copy link
Copy Markdown
Member

작업 내용

  • submit 이후 새로 생성된 COVER_LETTER_REVIEW Job을 after-commit 이벤트로 비동기 실행하도록 연결합니다.
  • worker가 PENDING Job을 PROCESSING으로 전환하고, 자기소개서/문항 snapshot으로 FirstReviewClient를 호출합니다.
  • 성공 시 ReviewVersionService.completeFirstReview(...)를 통해 ReviewVersion과 문항별 첨삭 결과를 저장합니다.
  • 실패 시 Job은 FAILED, CoverLetter는 REVIEW_FAILED로 전환합니다.
  • provider 실패와 출력 검증 실패를 각각 LLM_PROVIDER_ERROR, LLM_OUTPUT_VALIDATION_FAILED로 저장합니다.
  • 실제 OpenAI 호출 없이 fake client 기반 worker/event 테스트를 추가합니다.

관련 이슈

문서 반영

  • 반영한 문서:
    • docs/status.md
    • docs/api/cover-letters.md
    • docs/api/llm-jobs.md

확인 결과

  • ./gradlew test
  • ./gradlew check
  • 기타: git diff --check
  • 실행하지 못함. 이유:

Summary by CodeRabbit

  • 새 기능

    • 자기소개서 제출 후 최초 첨삭이 비동기로 처리되도록 변경되어, 제출 직후 상태가 더 명확하게 반영됩니다.
    • 첨삭 결과에 따라 리뷰 완료 또는 리뷰 실패 상태로 자동 전환됩니다.
  • 문서

    • 제출, 작업 상태 조회, 스트리밍 관련 API 문서를 최신 동작에 맞게 정리했습니다.
    • 진행 현황 문서의 로드맵과 후속 작업 후보를 업데이트했습니다.
  • 버그 수정

    • 첨삭 실패 시 상태와 결과 기록이 일관되게 남도록 개선했습니다.

submit 이후 생성된 최초 첨삭 Job을 커밋 후 비동기로 실행하고, 성공 시 ReviewVersion 저장, 실패 시 Job/CoverLetter 실패 상태를 반영한다.
@yong203 yong203 linked an issue Jun 28, 2026 that may be closed by this pull request
7 tasks
@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough PENDING: LlmJob 생성

PENDING --> PROCESSING: start() 호출
PROCESSING --> COMPLETED: completeFirstReview 성공
PROCESSING --> FAILED: fail() 호출
PENDING --> null반환: 이미 PENDING 아님
COMPLETED --> 무시: fail() 호출 시 skip
FAILED --> 무시: fail() 호출 시 skip

</diagram>
</layer>
<layer id="worker" title="FirstReviewJobWorker 실행 로직" depends_on="transaction_service_and_domain">
<summary>FirstReviewJobWorker.execute가 트랜잭션 서비스로 작업을 시작하고, FirstReviewClient 결과를 ReviewQuestionResultInput으로 매핑해 completeFirstReview를 호출하며, FirstReviewClientException 발생 시 fail로 위임한다.</summary>
<ranges>
range_b24b855e07a6
</ranges>
</layer>
<layer id="tests" title="워커 및 이벤트 통합 테스트" depends_on="worker">
<summary>FirstReviewJobWorkerTest(성공/프로바이더 실패/출력 검증 실패 시나리오)와 FirstReviewJobEventIntegrationTest(이벤트 발행 후 워커 호출, 중복 예약 방지)를 추가한다.</summary>
<ranges>
range_08c653931d40
range_f5f1007b1eca
range_a375b77a59bd
range_eece4567329f
range_686c16bd205a
range_058ba9514f7c
range_d0a955db741f
</ranges>
</layer>
<layer id="docs" title="API 및 상태 문서 갱신">
<summary>cover-letters.md에 비동기 워커 실행 흐름 및 성공/실패 상태 전환 설명이 추가되고, llm-jobs.md의 전제 문구와 attempt 예시 값, 스트림 미구현 설명이 수정되며, status.md의 REQ-005 진행 메모와 다음 이슈 후보가 갱신된다.</summary>
<ranges>
range_72b6363a87b5
range_b2dc6496aeec
range_054dce9434be
range_80b823a0d0e3
range_96984dbd2117
range_32512b0f1a72
</ranges>
</layer>
</cohort>
<unassigned_ranges>
</unassigned_ranges>
-->

## Walkthrough

`CoverLetterService.submit`에서 트랜잭션 커밋 이후 `LlmJobCreatedEvent`를 발행하고, `FirstReviewJobEventListener`가 `@Async`로 `FirstReviewJobWorker`를 실행하는 비동기 최초 첨삭 워커를 구현한다. 성공 시 `ReviewVersion`이 생성되고, 실패 시 `LlmJob`/`CoverLetter` 상태가 `FAILED`/`REVIEW_FAILED`로 전환된다.

## Changes

**최초 첨삭 비동기 워커 구현**

| Layer / File(s) | Summary |
|---|---|
| **LlmJobCreatedEvent 정의 및 AsyncConfig 활성화** <br> `src/main/java/com/daon/rewrite/llmjob/service/LlmJobCreatedEvent.java`, `src/main/java/com/daon/rewrite/global/config/AsyncConfig.java` | `jobId`를 보유하는 `LlmJobCreatedEvent` 레코드와 `@EnableAsync` `AsyncConfig` 설정 클래스를 추가해 이벤트 기반 비동기 처리 기반을 구성한다. |
| **CoverLetterService.submit에서 LlmJobCreatedEvent 발행** <br> `src/main/java/com/daon/rewrite/coverletter/service/CoverLetterService.java` | `submit` 트랜잭션 내 `LlmJob` 생성 후 `ApplicationEventPublisher`로 `LlmJobCreatedEvent`를 발행하도록 필드 주입 및 호출 코드를 추가한다. |
| **AFTER\_COMMIT 비동기 이벤트 리스너** <br> `src/main/java/com/daon/rewrite/reviewversion/service/FirstReviewJobEventListener.java` | `LlmJobCreatedEvent`를 `TransactionPhase.AFTER_COMMIT`에 수신하여 `@Async`로 `FirstReviewJobWorker.execute`를 호출하는 리스너를 추가한다. |
| **FirstReviewJobTransactionService + CoverLetter.failReview** <br> `src/main/java/com/daon/rewrite/reviewversion/service/FirstReviewJobTransactionService.java`, `src/main/java/com/daon/rewrite/reviewversion/service/FirstReviewWork.java`, `src/main/java/com/daon/rewrite/coverletter/entity/CoverLetter.java`, `src/main/java/com/daon/rewrite/reviewversion/client/FirstReviewClientException.java` | `start(jobId)`는 `PENDING` 잡을 잠금 조회해 `FirstReviewWork`로 변환하고, `fail(jobId, reason)`은 잡과 커버레터를 실패 상태로 전환한다. `CoverLetter.failReview(Instant)`가 추가되고, `FirstReviewClientException` 팩토리 메서드가 `public`으로 공개된다. |
| **FirstReviewJobWorker 실행 로직** <br> `src/main/java/com/daon/rewrite/reviewversion/service/FirstReviewJobWorker.java` | `execute(jobId)`가 트랜잭션 서비스로 작업을 시작하고, `FirstReviewClient` 결과를 `ReviewQuestionResultInput`으로 매핑해 `completeFirstReview`를 호출하며, `FirstReviewClientException` 발생 시 `transactionService.fail`로 위임한다. |
| **워커 및 이벤트 통합 테스트** <br> `src/test/java/com/daon/rewrite/reviewversion/service/FirstReviewJobWorkerTest.java`, `src/test/java/com/daon/rewrite/reviewversion/service/FirstReviewJobEventIntegrationTest.java` | 성공/프로바이더 실패/출력 검증 실패 시나리오를 검증하는 `FirstReviewJobWorkerTest`와, 이벤트 발행 후 워커 호출 및 중복 예약 방지를 검증하는 `FirstReviewJobEventIntegrationTest`를 추가한다. |
| **API 및 상태 문서 갱신** <br> `docs/api/cover-letters.md`, `docs/api/llm-jobs.md`, `docs/status.md` | 비동기 워커 실행 흐름과 성공/실패 상태 전환 설명을 `cover-letters.md`에 추가하고, `llm-jobs.md`의 전제 문구·`attempt` 예시 값·스트림 미구현 설명을 수정하며, `status.md`의 `REQ-005` 메모와 다음 이슈 후보를 갱신한다. |

## Possibly related PRs

- [Rewrite-Team/Rewrite-BE#41](https://github.com/Rewrite-Team/Rewrite-BE/pull/41): `CoverLetterService.submit`에서 PENDING `COVER_LETTER_REVIEW` Job을 생성하고 `CoverLetter.status`를 `REVIEWING`으로 전환하는 구현으로, 이번 PR이 이벤트 발행과 워커 실행을 연결하는 직접적인 선행 작업이다.
- [Rewrite-Team/Rewrite-BE#43](https://github.com/Rewrite-Team/Rewrite-BE/pull/43): 이번 PR의 `FirstReviewJobWorker`가 호출하는 `ReviewVersionService.completeFirstReview` 및 `ReviewVersion`/`ReviewVersionQuestionResult` 저장 로직이 구현된 PR이다.
- [Rewrite-Team/Rewrite-BE#45](https://github.com/Rewrite-Team/Rewrite-BE/pull/45): 이번 PR의 `FirstReviewJobWorker`가 의존하는 `FirstReviewClient`/`OpenAiFirstReviewClient` 및 `FirstReviewClientException` 응답 검증·매핑 구현이 포함된 PR이다.

## Suggested labels

`✨ Feature`

</details>

<!-- walkthrough_end -->
<!-- pre_merge_checks_walkthrough_start -->

<details>
<summary>🚥 Pre-merge checks | ✅ 4 | ❌ 1</summary>

### ❌ Failed checks (1 warning)

|     Check name     | Status     | Explanation                                                                          | Resolution                                                                         |
| :----------------: | :--------- | :----------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------- |
| Docstring Coverage | ⚠️ Warning | Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. | Write docstrings for the functions missing them to satisfy the coverage threshold. |

<details>
<summary>✅ Passed checks (4 passed)</summary>

|         Check name         | Status   | Explanation                                                        |
| :------------------------: | :------- | :----------------------------------------------------------------- |
|         Title check        | ✅ Passed | 제목이 최초 첨삭용 비동기 워커 구현이라는 핵심 변경을 간결하게 잘 요약합니다.                       |
|      Description check     | ✅ Passed | 작업 내용, 관련 이슈, 문서 반영, 확인 결과가 템플릿에 맞게 모두 채워져 있습니다.                   |
|     Linked Issues check    | ✅ Passed | after-commit 비동기 실행, 성공/실패 상태 전환, 오류 코드 매핑, 테스트 및 문서 갱신 요구를 충족합니다. |
| Out of Scope Changes check | ✅ Passed | 요구 범위 밖의 기능 추가나 계약 변경 없이 최초 첨삭 워커 관련 변경에 집중되어 있습니다.                |

</details>

</details>

<!-- pre_merge_checks_walkthrough_end -->
<!-- tips_start -->

---




<sub>Comment `@coderabbitai help` to get the list of available commands.</sub>

<!-- tips_end -->

@yong203 yong203 self-assigned this Jun 28, 2026
@yong203 yong203 added the ✨ Feature 새로운 기능 구현 label Jun 28, 2026
@github-actions

github-actions Bot commented Jun 28, 2026

Copy link
Copy Markdown

Backend CI Report

Item Result
Tests ✅ Passed
JaCoCo line coverage 96.35% (686/712 lines)
Coverage report ✅ Generated
Codecov upload ✅ Uploaded

View workflow run | View coverage details

@codecov

codecov Bot commented Jun 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 82.43243% with 13 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...sion/service/FirstReviewJobTransactionService.java 78.00% 5 Missing and 6 partials ⚠️
...te/reviewversion/service/FirstReviewJobWorker.java 86.66% 1 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@yong203 yong203 closed this Jun 28, 2026
@yong203 yong203 reopened this Jun 28, 2026
@yong203 yong203 merged commit 559088c into dev Jun 28, 2026
7 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Feature 새로운 기능 구현

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[✨Feat] 최초 첨삭 비동기 worker 구현

1 participant