Conversation
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: ASSERTIVE Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Note
|
| Cohort / File(s) | Summary |
|---|---|
에러 코드 및 도메인 모델 src/main/java/OneQ/OnSurvey/domain/survey/SurveyErrorCode.java, src/main/java/OneQ/OnSurvey/domain/survey/model/formRequest/FormConversionPayload.java, src/main/java/OneQ/OnSurvey/domain/survey/model/formRequest/FormConversionResponse.java |
새로운 FORM_CONVERSION_FAILED 에러 코드 추가 및 폼 변환 요청/응답을 위한 중첩된 레코드 구조(FormConversionPayload, FormConversionResponse와 그 하위 레코드들)를 정의합니다. |
이벤트 기반 아키텍처 src/main/java/OneQ/OnSurvey/domain/survey/model/formRequest/event/FormRequestConversionEvent.java, src/main/java/OneQ/OnSurvey/domain/survey/service/formRequest/FormCommandService.java |
FormRequest 저장 후 ApplicationEventPublisher를 통해 FormRequestConversionEvent를 발행하는 이벤트 기반 흐름을 구현합니다. |
폼 변환 오케스트레이션 src/main/java/OneQ/OnSurvey/domain/survey/service/formRequest/FormRequestLambda.java |
외부 Lambda 서비스와 통신하여 Google 폼을 설문으로 변환하는 복잡한 로직을 포함합니다. 설문 생성, 섹션/문제/선택지 처리, 유형 매핑, 트랜잭션 관리 및 상세한 로깅을 수행합니다. |
트랜잭션 관리 src/main/java/OneQ/OnSurvey/global/infra/transaction/TransactionHandler.java |
새로운 트랜잭션 경계(PROPAGATION_REQUIRES_NEW)에서 작업을 실행하는 유틸리티 컴포넌트를 제공합니다. |
알림 인프라 확장 src/main/java/OneQ/OnSurvey/global/infra/discord/DiscordAlarmService.java, src/main/java/OneQ/OnSurvey/global/infra/discord/DiscordAlarmAsyncFacade.java, src/main/java/OneQ/OnSurvey/global/infra/discord/notifier/AlertNotifier.java, src/main/java/OneQ/OnSurvey/global/infra/discord/notifier/DiscordAlertNotifier.java, src/main/java/OneQ/OnSurvey/global/infra/discord/notifier/NoOpAlertNotifier.java |
설문 변환 알림을 위한 비동기 메서드(sendSurveyConversionAsync)를 추가하고, Discord 알림 서비스에서 성공/실패 메시지를 구성하여 전송합니다. |
알림 데이터 모델 src/main/java/OneQ/OnSurvey/global/infra/discord/notifier/dto/SurveyConversionAlert.java |
변환 결과(성공/실패)를 모델링하는 SurveyConversionAlert 레코드 및 하위 레코드들(SurveyDetails, UnsupportedQuestion)과 팩토리 메서드를 정의합니다. |
Sequence Diagram(s)
sequenceDiagram
participant Client
participant FormCommandService
participant EventPublisher
participant FormRequestLambda
participant ExternalLambda
participant SurveyCommand
participant QuestionCommand
participant MemberFinder
participant AlertNotifier
Client->>FormCommandService: FormRequest 저장
FormCommandService->>FormCommandService: FormRequest 영속화
FormCommandService->>EventPublisher: FormRequestConversionEvent 발행
EventPublisher->>FormRequestLambda: convertGoogleFormIntoSurvey() 호출
FormRequestLambda->>ExternalLambda: FormConversionPayload 전송
ExternalLambda-->>FormRequestLambda: FormConversionResponse 반환
FormRequestLambda->>MemberFinder: 요청자 이메일로 회원 조회
loop 각 변환 결과 처리
FormRequestLambda->>SurveyCommand: 설문 생성 (upsertSurvey)
SurveyCommand-->>FormRequestLambda: surveyId 반환
FormRequestLambda->>QuestionCommand: 섹션 생성 (upsertSections)
FormRequestLambda->>QuestionCommand: 문제 생성 (upsertInfoList)
FormRequestLambda->>QuestionCommand: 선택지 생성 (upsertChoiceOptionList)
end
FormRequestLambda->>AlertNotifier: SurveyConversionAlert 전송
AlertNotifier-->>Client: 변환 결과 알림 (비동기)
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~75 minutes
Possibly related PRs
- ✨ OMF-149 설문 폼 등록 기능 #99: 동일한 form-request 기능을 수정하고 SurveyErrorCode 열거형과 FormCommandService 동작을 변경합니다.
- ✨ OMF-155 구글 폼 변환을 위한 섹션 구현 #100: 설문/문제 변환 및 영속화 흐름을 확장하여 섹션 기반 네비게이션과 질문 생성을 처리합니다.
- ♻️ OMF-133 TOSS 사용자정보 요청 시 발생하는 예외에 대한 로깅 및 Sentry 알림 처리 #96: AlertNotifier, DiscordAlarmAsyncFacade, DiscordAlertNotifier, NoOpAlertNotifier, DiscordAlarmService 등 동일한 알림 인프라 클래스들에 새로운 비동기 알림 메서드를 추가합니다.
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | 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. |
✅ Passed checks (2 passed)
| Check name | Status | Explanation |
|---|---|---|
| Title check | ✅ Passed | PR 제목은 'OMF-235 폼 변환 자동화 작업'으로 변경 사항의 핵심을 명확하게 요약하고 있습니다. |
| Description check | ✅ Passed | PR 설명은 템플릿의 모든 필수 섹션(Related Issue, Task Details)을 포함하고 있으며, 작업 항목들이 체계적으로 기술되어 있습니다. |
✏️ Tip: You can configure your own custom pre-merge checks in the settings.
✨ Finishing Touches
🧪 Generate unit tests (beta)
- Create PR with unit tests
- Post copyable unit tests in a comment
- Commit unit tests in branch
feat/OMF-235
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@src/main/java/OneQ/OnSurvey/domain/survey/service/formRequest/FormRequestLambda.java`:
- Around line 116-123: The catch block in FormRequestLambda currently only logs
the exception and exits, so failures aren't added to alert.details; update the
exception handler inside the try/catch surrounding survey creation (the
catch(Exception e) block) to also add a failure detail to alert.details(), e.g.
call
alert.details().add(SurveyConversionAlert.SurveyDetails.failure(event.requestId()
or result.url() as appropriate, e.getMessage())) so the alert contains the
creation failure (include requestId and the exception message) and keep the
existing log call; ensure you reference the existing alert variable and use
SurveyConversionAlert.SurveyDetails.failure(...) consistent with the
success/failure usage elsewhere.
- Around line 220-230: The loop currently pairs savedInfoList and
questionUpsertInfoList by index which can mis-map options because savedInfoList
is sorted by Question.getOrder; instead, build a Map keyed by questionId from
the original questionUpsertInfoList and look up the matching originalInfo for
each savedInfo (use savedInfo.getQuestionId()) before constructing
OptionUpsertDto items — mirror the approach used in
SurveyFormFacade.buildOptionUpsertDtosFromSavedQuestions and update the code
around savedInfoList/questionUpsertInfoList usage (and the call site
upsertQuestionList/QuestionUpsertDto handling) so options are matched by
questionId rather than list index.
- Around line 60-67: The Lambda POST call in FormRequestLambda using
webClient.post().uri(lambdaUrl).bodyValue(payload).retrieve().bodyToMono(FormConversionResponse.class).block()
lacks error handling so HTTP 4xx/5xx responses throw WebClientResponseException
and skip the response == null branch (preventing
alertNotifier.sendSurveyConversionAsync from running); update this call to
handle non-2xx status with .onStatus(...) to map errors to a meaningful
FormConversionResponse or a handled exception and add .onErrorResume(...) to
catch WebClientResponseException/timeout errors and return a fallback
FormConversionResponse (or trigger alertNotifier.sendSurveyConversionAsync in
the resume path), and ensure the request uses an appropriate per-request timeout
(override the global WebClientConfig 2000ms timeout for the lambda call) so the
Lambda call has sufficient time.
In `@src/main/java/OneQ/OnSurvey/domain/survey/SurveyErrorCode.java`:
- Around line 32-33: The enum SurveyErrorCode has inconsistent error-code
naming: change the FORM_CONVERSION_FAILED enum entry in SurveyErrorCode so its
code string follows the existing pattern (use "FORM_REQUEST_400" instead of
"FORM_REQUEST_001") to match other entries like FORM_REQUEST_NOT_FOUND and HTTP
400 semantics; update only the first argument of the FORM_CONVERSION_FAILED
entry to "FORM_REQUEST_400" and keep the message and HttpStatus.BAD_REQUEST
unchanged.
In `@src/main/java/OneQ/OnSurvey/global/infra/discord/DiscordAlarmService.java`:
- Line 140: Fix the typo in the string literal used when building the alarm
message in DiscordAlarmService: replace "tittle" with "title" in the string
passed to StringBuilder (the line that calls .append("\u3000 tittle:
").append(safe(d.title())).append('\n')), so the message reads "title" while
keeping the surrounding formatting and safe(d.title()) call unchanged.
- Line 158: The error line in DiscordAlarmService (the append chain that builds
"* error: " using safe(alert.error())) is missing the opening backtick; change
the string assembly so the error text is wrapped in backticks (matching the
other alert formatting), e.g. prepend a backtick before safe(alert.error()) and
keep the closing backtick and newline; locate the append call in
DiscordAlarmService where safe(alert.error()) is used and update that append
sequence to include the opening backtick so formatting is consistent with other
alarm methods.
In
`@src/main/java/OneQ/OnSurvey/global/infra/discord/notifier/NoOpAlertNotifier.java`:
- Around line 12-17: NoOpAlertNotifier is annotated for the local profile but
still invokes the external DiscordAlarmAsyncFacade (the private final field
discord) in its methods (lines ~31-34), so remove the direct calls to discord
and replace them with a true no-op behavior (e.g., log locally or return a
completed future) inside NoOpAlertNotifier's alert methods; locate Anywhere the
class references discord (calls to discord.send/notify/execute) and replace
those invocations with non-networking stubs so local runs never transmit to the
production Discord channel.
ℹ️ Review info
Configuration used: Path: .coderabbit.yml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (13)
src/main/java/OneQ/OnSurvey/domain/survey/SurveyErrorCode.javasrc/main/java/OneQ/OnSurvey/domain/survey/model/formRequest/FormConversionPayload.javasrc/main/java/OneQ/OnSurvey/domain/survey/model/formRequest/FormConversionResponse.javasrc/main/java/OneQ/OnSurvey/domain/survey/model/formRequest/event/FormRequestConversionEvent.javasrc/main/java/OneQ/OnSurvey/domain/survey/service/formRequest/FormCommandService.javasrc/main/java/OneQ/OnSurvey/domain/survey/service/formRequest/FormRequestLambda.javasrc/main/java/OneQ/OnSurvey/global/infra/discord/DiscordAlarmAsyncFacade.javasrc/main/java/OneQ/OnSurvey/global/infra/discord/DiscordAlarmService.javasrc/main/java/OneQ/OnSurvey/global/infra/discord/notifier/AlertNotifier.javasrc/main/java/OneQ/OnSurvey/global/infra/discord/notifier/DiscordAlertNotifier.javasrc/main/java/OneQ/OnSurvey/global/infra/discord/notifier/NoOpAlertNotifier.javasrc/main/java/OneQ/OnSurvey/global/infra/discord/notifier/dto/SurveyConversionAlert.javasrc/main/java/OneQ/OnSurvey/global/infra/transaction/TransactionHandler.java
src/main/java/OneQ/OnSurvey/domain/survey/service/formRequest/FormRequestLambda.java
Outdated
Show resolved
Hide resolved
src/main/java/OneQ/OnSurvey/domain/survey/service/formRequest/FormRequestLambda.java
Show resolved
Hide resolved
src/main/java/OneQ/OnSurvey/domain/survey/service/formRequest/FormRequestLambda.java
Outdated
Show resolved
Hide resolved
src/main/java/OneQ/OnSurvey/global/infra/discord/DiscordAlarmService.java
Outdated
Show resolved
Hide resolved
src/main/java/OneQ/OnSurvey/global/infra/discord/DiscordAlarmService.java
Outdated
Show resolved
Hide resolved
src/main/java/OneQ/OnSurvey/global/infra/discord/notifier/NoOpAlertNotifier.java
Outdated
Show resolved
Hide resolved
da71993 to
6e37565
Compare
# Conflicts: # src/main/java/OneQ/OnSurvey/domain/question/entity/ChoiceOption.java # src/main/java/OneQ/OnSurvey/domain/question/entity/Question.java # src/main/java/OneQ/OnSurvey/domain/question/entity/question/Choice.java # src/main/java/OneQ/OnSurvey/domain/question/entity/question/DateAnswer.java # src/main/java/OneQ/OnSurvey/domain/question/entity/question/LongAnswer.java # src/main/java/OneQ/OnSurvey/domain/question/entity/question/NPS.java # src/main/java/OneQ/OnSurvey/domain/question/entity/question/NumberAnswer.java # src/main/java/OneQ/OnSurvey/domain/question/entity/question/Rating.java # src/main/java/OneQ/OnSurvey/domain/question/entity/question/ShortAnswer.java # src/main/java/OneQ/OnSurvey/domain/question/model/dto/type/ChoiceDto.java # src/main/java/OneQ/OnSurvey/domain/question/model/dto/type/DateDto.java # src/main/java/OneQ/OnSurvey/domain/question/model/dto/type/DefaultQuestionDto.java # src/main/java/OneQ/OnSurvey/domain/question/model/dto/type/RatingDto.java # src/main/java/OneQ/OnSurvey/domain/question/service/QuestionCommandService.java
✨ Related Issue
📌 Task Details
💬 Review Requirements (Optional)
Summary by CodeRabbit
릴리즈 노트
새로운 기능