-
Notifications
You must be signed in to change notification settings - Fork 1
[Fix] 검색-RAG 비동기 처리 전환 (동시 요청 시 응답 유실 방지) #223
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
bae9acd
feat: #218 비동기 RAG 처리를 위한 데이터 계층 준비
kangcheolung ef68ba5
feat: #218 RagFacade를 enqueue/processJob으로 분리
kangcheolung 2e8b42d
feat: #218 RAG Job Worker 추가
kangcheolung 2cb6a0b
feat: #218 RAG 답변 완료 WebSocket 알림
kangcheolung 04300b7
feat: #218 검색-RAG API를 비동기 계약으로 전환
kangcheolung d709863
chore: #218 Ollama 타임아웃 설정을 비동기 전환에 맞게 재조정
kangcheolung 806f696
test: #218 비동기 RAG 처리 단위·통합 테스트
kangcheolung b0d9bd6
feat: #218 검색 결과 먼저 표시하고 AI 답변은 비동기로 갱신하는 UI
kangcheolung 6f5e2ac
test: #218 SearchResponse ragStatus 필드 추가에 맞춰 프론트 테스트 갱신
kangcheolung 9ff4a62
docs: #218 비동기 RAG Job 큐 설계 문서
kangcheolung aefee9b
docs: #35, #44 설계 문서에 이후 변경 이력 추가
kangcheolung 4b939d5
fix: #218 CodeRabbit 지적 반영 — Worker 경합·예외 처리, 프론트 stale response 방지
kangcheolung 7333d71
test: #218 CodeRabbit 지적 반영 — Worker 예외/경합 처리 회귀 테스트
kangcheolung b0261c7
docs: #218 CodeRabbit 지적 반영 — 코드 펜스 언어 태그 지정
kangcheolung ee28d82
docs: #218 CodeRabbit 리뷰로 고친 버그 3건 설계 문서에 반영
kangcheolung File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
16 changes: 16 additions & 0 deletions
16
backend/src/main/java/com/opensource/docgrid/domain/rag/config/RagSchedulingConfig.java
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| package com.opensource.docgrid.domain.rag.config; | ||
|
|
||
| import org.springframework.context.annotation.Configuration; | ||
| import org.springframework.scheduling.annotation.EnableScheduling; | ||
|
|
||
| /** | ||
| * {@code WorkerSchedulingConfig} 등 다른 도메인의 {@code @EnableScheduling}과 별개로 켠다 — | ||
| * 그쪽은 {@code indexing.worker.enabled} 조건부라 꺼질 수 있지만, {@link | ||
| * com.opensource.docgrid.domain.rag.service.RagJobWorker}는 검색 API의 핵심 경로라 조건 없이 | ||
| * 항상 돌아야 한다. {@code @EnableScheduling}을 여러 설정 클래스에 중복 선언해도 Spring이 | ||
| * 안전하게 병합하므로 문제없다. | ||
| */ | ||
| @Configuration | ||
| @EnableScheduling | ||
| public class RagSchedulingConfig { | ||
| } |
38 changes: 38 additions & 0 deletions
38
...nd/src/main/java/com/opensource/docgrid/domain/rag/controller/RagWebSocketController.java
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| package com.opensource.docgrid.domain.rag.controller; | ||
|
|
||
| import org.springframework.messaging.simp.SimpMessagingTemplate; | ||
| import org.springframework.stereotype.Component; | ||
|
|
||
| import lombok.RequiredArgsConstructor; | ||
|
|
||
| /** | ||
| * RAG 답변이 준비됐음을 요청한 사용자에게만 push하는 전송 계층 (#218). | ||
| * | ||
| * <p>{@code DashboardWebSocketController}(/topic/dashboard, 전체 브로드캐스트)와 달리, 이건 검색 | ||
| * 요청을 보낸 그 유저 한 명에게만 전달돼야 한다 — 관리자 전용 브로드캐스트 채널을 재사용할 수 없는 | ||
| * 이유다. {@code convertAndSendToUser}는 {@code StompAuthChannelInterceptor}가 CONNECT 시점에 | ||
| * 세션에 부착한 Principal(이메일)로 목적지를 사용자별로 격리한다 — 다른 유저는 같은 목적지 | ||
| * ({@code /user/queue/rag-answer})를 구독해도 이 메시지를 받지 않으므로, 대시보드처럼 별도의 | ||
| * 구독 인가 Interceptor가 필요 없다. | ||
| * | ||
| * <p>본문은 트리거 용도로만 쓴다. {@code useDashboardSocket}과 동일하게, 프론트는 이 메시지를 | ||
| * "다시 조회해야 한다"는 신호로만 쓰고 최신 상태는 REST로 다시 읽는다 — Push 페이로드와 실제 | ||
| * DB 상태가 어긋날 걱정 없이 항상 단일 진실 소스(REST)를 신뢰할 수 있다. | ||
| */ | ||
| @Component | ||
| @RequiredArgsConstructor | ||
| public class RagWebSocketController { | ||
|
|
||
| private static final String RAG_ANSWER_QUEUE = "/queue/rag-answer"; | ||
|
|
||
| private final SimpMessagingTemplate messagingTemplate; | ||
|
|
||
| public void notifyAnswerReady(String userEmail, Long queryId) { | ||
| messagingTemplate.convertAndSendToUser(userEmail, RAG_ANSWER_QUEUE, new RagAnswerReadyEvent(queryId)); | ||
| } | ||
|
|
||
| // 완료 알림의 최소 트리거 페이로드 — 답변 본문은 담지 않는다. 프론트가 이 이벤트를 받으면 | ||
| // 항상 GET /search/{queryId}로 다시 조회해야 하며, 이 record 자체를 최종 상태로 신뢰하면 안 된다. | ||
| private record RagAnswerReadyEvent(Long queryId) { | ||
| } | ||
| } |
16 changes: 16 additions & 0 deletions
16
backend/src/main/java/com/opensource/docgrid/domain/rag/dto/RagEnqueueOutcome.java
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| package com.opensource.docgrid.domain.rag.dto; | ||
|
|
||
| /** | ||
| * RagFacade.enqueue() 반환 타입 — 검색 후보가 없어(NO_CONTEXT) LLM 호출 없이 즉시 끝난 경우와, | ||
| * PROCESSING으로 Job 큐에 올라가 Worker의 처리를 기다려야 하는 경우를 구분한다. | ||
| */ | ||
| public record RagEnqueueOutcome(RagAnswer immediateAnswer, boolean pending) { | ||
|
|
||
| public static RagEnqueueOutcome stillPending() { | ||
| return new RagEnqueueOutcome(null, true); | ||
| } | ||
|
|
||
| public static RagEnqueueOutcome done(RagAnswer answer) { | ||
| return new RagEnqueueOutcome(answer, false); | ||
| } | ||
| } |
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
12 changes: 12 additions & 0 deletions
12
...end/src/main/java/com/opensource/docgrid/domain/rag/repository/RagResponseRepository.java
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,20 @@ | ||
| package com.opensource.docgrid.domain.rag.repository; | ||
|
|
||
| import java.util.Optional; | ||
|
|
||
| import org.springframework.data.jpa.repository.EntityGraph; | ||
| import org.springframework.data.jpa.repository.JpaRepository; | ||
|
|
||
| import com.opensource.docgrid.domain.rag.entity.RagResponse; | ||
| import com.opensource.docgrid.domain.search.enums.ResultStatus; | ||
|
|
||
| public interface RagResponseRepository extends JpaRepository<RagResponse, Long> { | ||
|
|
||
| // Worker가 순서대로 하나씩 꺼내 처리한다 — Worker가 1개뿐이라 별도 락/claim 없이도 안전하다. | ||
| // query/query.user를 미리 fetch해 Worker가 트랜잭션 밖(WebSocket push 시점)에서 | ||
| // job.getQuery().getUser().getEmail()에 접근해도 LazyInitializationException이 나지 않게 한다. | ||
| @EntityGraph(attributePaths = {"query", "query.user"}) | ||
| Optional<RagResponse> findFirstByStatusOrderByCreatedAtAsc(ResultStatus status); | ||
|
|
||
| Optional<RagResponse> findByQuery_Id(Long queryId); | ||
| } | ||
4 changes: 4 additions & 0 deletions
4
...rc/main/java/com/opensource/docgrid/domain/rag/repository/ResponseCitationRepository.java
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,12 @@ | ||
| package com.opensource.docgrid.domain.rag.repository; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| import org.springframework.data.jpa.repository.JpaRepository; | ||
|
|
||
| import com.opensource.docgrid.domain.rag.entity.ResponseCitation; | ||
|
|
||
| public interface ResponseCitationRepository extends JpaRepository<ResponseCitation, Long> { | ||
|
|
||
| List<ResponseCitation> findByResponse_IdOrderByCitationOrder(Long responseId); | ||
| } |
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
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.