Skip to content

[Feat] RAGOps Dashboard 관리자 재처리 API - #150

Merged
kangcheolung merged 7 commits into
developfrom
feature/148
Aug 11, 2026
Merged

[Feat] RAGOps Dashboard 관리자 재처리 API#150
kangcheolung merged 7 commits into
developfrom
feature/148

Conversation

@kangcheolung

@kangcheolung kangcheolung commented Aug 11, 2026

Copy link
Copy Markdown
Member

Summary

  • POST /admin/embedding-jobs/{jobId}/retry (단건), POST /admin/embedding-jobs/retry-all (전체) 추가
  • 단건 재처리는 A 담당자의 EmbeddingJobManualRetryService.retry()를 그대로 호출한 뒤 최신 대시보드 집계를 WebSocket(/topic/dashboard)으로 push
  • 전체 재처리는 EmbeddingJobRepository.findAllByStatus(FAILED)로 직접 조회(A의 REST 엔드포인트를 내부 호출하지 않음) 후 순차 재처리, 개별 실패는 catch하고 성공 건수만 집계, 1건 이상 성공 시에만 push
  • 단건 재처리 응답은 새 DTO 없이 A의 ManualRetriedIndexingJobResponse를 그대로 반환 (스펙 초안보다 A가 이미 더 풍부한 정보를 제공)
  • 404/409 예외 처리 코드 없음 — A가 이미 EMBEDDING_JOB_NOT_FOUND/EMBEDDING_JOB_MANUAL_RETRY_NOT_ALLOWED로 구분해서 던지고, 기존 GlobalExceptionHandler가 전역 처리하므로 B는 그대로 propagate만 함

설계 결정 — Command Service에 클래스 레벨 @Transactional을 의도적으로 두지 않음

EmbeddingJobRetryService가 프로젝트 컨벤션(Command는 클래스 레벨 @Transactional 필수)과 다르게 트랜잭션을 열지 않습니다. retryAllFailedJobs()가 이 메서드 자체에서 트랜잭션을 열면 내부에서 호출하는 A의 retry()가 그 트랜잭션에 참여(REQUIRED)하게 되어, 중간 Job에서 예외가 나는 순간 스프링이 트랜잭션을 rollback-only로 표시합니다 — catch로 잡아도 이미 성공한 이전 Job들까지 커밋 시점에 전부 롤백됩니다. 트랜잭션을 안 열어야 retry() 호출마다 A Service 자신의 @Transactional이 독립된 새 트랜잭션을 만들어 각자 커밋됩니다. 상세 근거는 docs/design/kangcheolung-#148-ragops-dashboard-retry.md 4.4절 참고.

Test plan

  • EmbeddingJobRetryServiceTest 단위 테스트 4건 (단건 재처리+push, 부분 실패 시 성공 건수만 집계+push, FAILED 0건 시 push 안 함, 전부 실패 시 push 안 함)
  • EmbeddingJobRetryTransactionIsolationIntegrationTest — 위 트랜잭션 독립성 설계 근거를 Mock이 아닌 실제 PostgreSQL로 검증 (이슈 To-do엔 없었으나 Mock으로는 증명 불가능한 검증 공백이라 추가). FAILED Job 3건 중 1건(문서 soft-delete)만 실패하도록 만들고, 나머지 2건이 실제로 PENDING으로 커밋됨을 확인
  • ./gradlew build 전체 회귀 테스트 통과 — 총 751개, failures 0, errors 0

상세 설계

docs/design/kangcheolung-#148-ragops-dashboard-retry.md

closes #148

🤖 Generated with Claude Code

Summary by CodeRabbit

  • 새 기능

    • 관리자용 임베딩 작업 재처리 기능을 추가했습니다.
    • 개별 작업을 다시 처리하거나, 실패한 작업 전체를 한 번에 재처리할 수 있습니다.
    • 재처리 성공 건수와 처리 결과 메시지를 확인할 수 있습니다.
    • 재처리 결과가 대시보드에 실시간으로 반영됩니다.
    • 일부 작업이 실패해도 성공한 작업은 정상 처리됩니다.
  • 버그 수정

    • 실패한 작업의 재처리 중 오류가 발생해도 다른 작업의 처리가 중단되지 않도록 개선했습니다.
  • 테스트

    • 개별·전체 재처리, 부분 실패 및 데이터 처리 결과에 대한 검증을 추가했습니다.

kangcheolung and others added 6 commits August 11, 2026 15:52
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@kangcheolung kangcheolung changed the title [Feature] RAGOps Dashboard 관리자 재처리 API [Feat] RAGOps Dashboard 관리자 재처리 API Aug 11, 2026
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@kangcheolung, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 50 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: efa47f97-13a5-4087-909c-6e15d5b0a6a3

📥 Commits

Reviewing files that changed from the base of the PR and between 616cdae and 9234632.

📒 Files selected for processing (3)
  • src/main/java/com/opensource/docgrid/domain/dashboard/service/command/EmbeddingJobRetryService.java
  • src/test/java/com/opensource/docgrid/domain/dashboard/service/command/EmbeddingJobRetryServiceTest.java
  • src/test/java/com/opensource/docgrid/domain/dashboard/service/command/EmbeddingJobRetryTransactionIsolationIntegrationTest.java
📝 Walkthrough

Walkthrough

관리자용 FAILED Embedding Job 재처리 기능을 추가했다. 단건·전체 POST API를 제공한다. 기존 재처리 서비스로 상태를 전환하고 성공 시 대시보드를 갱신한다. 단위 테스트와 PostgreSQL 트랜잭션 독립성 테스트를 추가했다.

Changes

Embedding Job 재처리

Layer / File(s) Summary
재처리 API 계약과 진입점
docs/design/.../kangcheolung-#148-ragops-dashboard-retry.md, src/main/java/.../controller/EmbeddingJobRetryController.java, src/main/java/.../dto/response/RetryAllJobsResponse.java
관리자용 단건·전체 재처리 API와 RetryAllJobsResponse 계약을 추가했다. 양수 jobId 검증과 성공·403·404·409 응답 문서를 정의했다.
단건·전체 재처리 실행
src/main/java/.../service/command/EmbeddingJobRetryService.java, docs/design/.../kangcheolung-#148-ragops-dashboard-retry.md
단건 재처리는 기존 재처리 서비스 호출 후 대시보드를 갱신한다. 전체 재처리는 FAILED 작업을 순차 처리하고 개별 실패를 건너뛴다. 성공 건수가 있을 때만 WebSocket push를 실행한다.
재처리 및 트랜잭션 검증
src/test/java/.../EmbeddingJobRetryServiceTest.java, src/test/java/.../EmbeddingJobRetryTransactionIsolationIntegrationTest.java, docs/design/.../kangcheolung-#148-ragops-dashboard-retry.md
단위 테스트가 응답과 대시보드 push 조건을 검증한다. PostgreSQL 통합 테스트가 성공 작업 두 개의 PENDING 커밋과 실패 작업의 FAILED 유지를 검증한다.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Admin as 관리자
  participant Controller as EmbeddingJobRetryController
  participant RetryService as EmbeddingJobRetryService
  participant Repository as EmbeddingJobRepository
  participant ManualRetry as EmbeddingJobManualRetryService
  participant Dashboard as DashboardWebSocketController

  Admin->>Controller: 재처리 POST 요청
  Controller->>RetryService: retryJob 또는 retryAllFailedJobs
  RetryService->>Repository: FAILED 작업 조회
  RetryService->>ManualRetry: 작업별 retry 호출
  RetryService->>Dashboard: 성공 시 sendDashboardUpdate
  RetryService-->>Controller: 재처리 결과 반환
  Controller-->>Admin: ApiResponse 반환
Loading

Possibly related PRs

  • DocGrid/backend#109: 기존 수동 임베딩 작업 재처리 로직과 응답·서비스 패턴을 재사용한다.
  • DocGrid/backend#136: 재처리 후 대시보드 집계를 갱신하는 흐름과 직접 연결된다.
  • DocGrid/backend#139: 재처리 성공 후 DashboardWebSocketController.sendDashboardUpdate()를 호출하는 흐름과 연결된다.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed [ #148 ] 단건·전체 재처리 API, 기존 서비스 재사용, 실패 작업 처리, 권한·예외 처리와 테스트 요구사항을 구현했습니다.
Out of Scope Changes check ✅ Passed 구현 코드, 설계 문서와 단위·PostgreSQL 통합 테스트가 모두 이슈 #148의 재처리 기능 범위에 포함됩니다.
Title check ✅ Passed 제목이 관리자용 FAILED 임베딩 작업 재처리 API 추가라는 주요 변경 사항을 명확하고 간결하게 설명합니다.
Description check ✅ Passed 주요 변경, 설계 결정, 테스트 계획, 이슈 연결을 설명했으며 템플릿의 선택 항목을 제외한 핵심 내용이 대부분 포함되어 있습니다.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/148

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/test/java/com/opensource/docgrid/domain/dashboard/service/command/EmbeddingJobRetryServiceTest.java (1)

44-44: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

실제 컴포넌트 이름을 사용하세요.

제공된 코드에는 A 서비스A 담당자라는 기술 식별자가 없습니다. A가 내부 작업 구분자라면 커밋된 테스트 이름과 Javadoc에서 제거하세요. 두 위치 모두 EmbeddingJobManualRetryService를 직접 참조하세요.

  • src/test/java/com/opensource/docgrid/domain/dashboard/service/command/EmbeddingJobRetryServiceTest.java#L44-L44: A 서비스EmbeddingJobManualRetryService로 변경하세요.
  • src/test/java/com/opensource/docgrid/domain/dashboard/service/command/EmbeddingJobRetryTransactionIsolationIntegrationTest.java#L29-L32: A 담당자 소유 표현을 제거하고 실제 서비스 이름으로 설명하세요.

As per coding guidelines, "When modifying a Java file, update affected class, method, field, or flow comments so they remain consistent with the implementation."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/com/opensource/docgrid/domain/dashboard/service/command/EmbeddingJobRetryServiceTest.java`
at line 44, Update the test descriptions to use the actual
EmbeddingJobManualRetryService name: in EmbeddingJobRetryServiceTest.java lines
44-44, replace “A 서비스”; in
EmbeddingJobRetryTransactionIsolationIntegrationTest.java lines 29-32, remove
the “A 담당자” ownership wording and describe the behavior using
EmbeddingJobManualRetryService.

Source: Coding guidelines

src/main/java/com/opensource/docgrid/domain/dashboard/service/command/EmbeddingJobRetryService.java (1)

47-72: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

순차 실행 흐름에 번호 주석을 추가하세요.

retryJob()retryAllFailedJobs()는 상태 변경, 집계 조회, 대시보드 전송 순서에 의존합니다. 각 중요한 단계 앞에 1., 2., 3. 번호 주석을 추가하세요. 현재의 메서드 제목 주석만으로는 실행 순서와 성공 조건을 설명하지 못합니다.

As per coding guidelines, "For sequential execution flows, add numbered comments such as 1., 2., 3., and 4. at the relevant steps" 규칙을 적용했습니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/opensource/docgrid/domain/dashboard/service/command/EmbeddingJobRetryService.java`
around lines 47 - 72, Add numbered step comments to the sequential flows in
retryJob() and retryAllFailedJobs(), covering the retry/state-change operation,
summary retrieval, dashboard update, failed-job iteration and count aggregation,
and response construction as applicable. Use `1.`, `2.`, `3.`, and `4.` directly
before the relevant statements while preserving the existing execution order and
success conditions.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/design/kangcheolung-`#148-ragops-dashboard-retry.md:
- Around line 106-109: Replace the internal labels 이슈1 and 이슈2 in the documented
retry flow with the identified issue references `#134` and `#137`, respectively,
while preserving the existing service and method references.

In
`@src/main/java/com/opensource/docgrid/domain/dashboard/service/command/EmbeddingJobRetryService.java`:
- Line 50: EmbeddingJobRetryService의 재처리 트랜잭션과 대시보드 WebSocket 전송을 분리하세요. 단건
재시도(50-50)와 전체 재시도(69-69)는 커밋된 EmbeddingJobManualRetryService.retry() 결과로 API
응답을 확정하고, dashboardWebSocketController.sendDashboardUpdate 호출은 내구성 있는 후속 전송 및
재시도 경로로 이동해 전송 실패가 API 성공 결과를 변경하지 않도록 하세요.

---

Nitpick comments:
In
`@src/main/java/com/opensource/docgrid/domain/dashboard/service/command/EmbeddingJobRetryService.java`:
- Around line 47-72: Add numbered step comments to the sequential flows in
retryJob() and retryAllFailedJobs(), covering the retry/state-change operation,
summary retrieval, dashboard update, failed-job iteration and count aggregation,
and response construction as applicable. Use `1.`, `2.`, `3.`, and `4.` directly
before the relevant statements while preserving the existing execution order and
success conditions.

In
`@src/test/java/com/opensource/docgrid/domain/dashboard/service/command/EmbeddingJobRetryServiceTest.java`:
- Line 44: Update the test descriptions to use the actual
EmbeddingJobManualRetryService name: in EmbeddingJobRetryServiceTest.java lines
44-44, replace “A 서비스”; in
EmbeddingJobRetryTransactionIsolationIntegrationTest.java lines 29-32, remove
the “A 담당자” ownership wording and describe the behavior using
EmbeddingJobManualRetryService.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ccced043-cd58-48a4-a621-2260dcbd933a

📥 Commits

Reviewing files that changed from the base of the PR and between 93a96cb and 616cdae.

📒 Files selected for processing (6)
  • docs/design/kangcheolung-#148-ragops-dashboard-retry.md
  • src/main/java/com/opensource/docgrid/domain/dashboard/controller/EmbeddingJobRetryController.java
  • src/main/java/com/opensource/docgrid/domain/dashboard/dto/response/RetryAllJobsResponse.java
  • src/main/java/com/opensource/docgrid/domain/dashboard/service/command/EmbeddingJobRetryService.java
  • src/test/java/com/opensource/docgrid/domain/dashboard/service/command/EmbeddingJobRetryServiceTest.java
  • src/test/java/com/opensource/docgrid/domain/dashboard/service/command/EmbeddingJobRetryTransactionIsolationIntegrationTest.java

Comment on lines +106 to +109
`embeddingJobManualRetryService`는 A 담당자가 만든 서비스를 그대로 주입받아 호출한다.
`retry(jobId)`가 예외 없이 반환하면(=성공) 바로 이슈1의 `DashboardQueryService.getSummary()`로
최신 집계를 다시 계산하고, 이슈2의 `DashboardWebSocketController.sendDashboardUpdate()`로
`/topic/dashboard` 구독자에게 push한다. 예외 처리 코드가 하나도 없는데, 이유는 4.4절 참고.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

내부 순번 라벨을 실제 이슈 번호로 교체하세요.

이슈1이슈2는 문서 외부에서 의미를 알 수 없습니다. 앞부분에서 식별한 실제 이슈 번호인 #134#137을 사용하세요.

수정 예시
-`retry(jobId)`가 예외 없이 반환하면(=성공) 바로 이슈1의 `DashboardQueryService.getSummary()`로
-최신 집계를 다시 계산하고, 이슈2의 `DashboardWebSocketController.sendDashboardUpdate()`로
+`retry(jobId)`가 예외 없이 반환하면(=성공) 바로 이슈 `#134의` `DashboardQueryService.getSummary()`로
+최신 집계를 다시 계산하고, 이슈 `#137의` `DashboardWebSocketController.sendDashboardUpdate()`로

As per coding guidelines, "Never expose private numbered PR sequence labels in ... committed documents" 규칙을 적용했습니다.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
`embeddingJobManualRetryService`는 A 담당자가 만든 서비스를 그대로 주입받아 호출한다.
`retry(jobId)`가 예외 없이 반환하면(=성공) 바로 이슈1의 `DashboardQueryService.getSummary()`
최신 집계를 다시 계산하고, 이슈2의 `DashboardWebSocketController.sendDashboardUpdate()`
`/topic/dashboard` 구독자에게 push한다. 예외 처리 코드가 하나도 없는데, 이유는 4.4절 참고.
`embeddingJobManualRetryService`는 A 담당자가 만든 서비스를 그대로 주입받아 호출한다.
`retry(jobId)`가 예외 없이 반환하면(=성공) 바로 이슈 `#134의` `DashboardQueryService.getSummary()`
최신 집계를 다시 계산하고, 이슈 `#137의` `DashboardWebSocketController.sendDashboardUpdate()`
`/topic/dashboard` 구독자에게 push한다. 예외 처리 코드가 하나도 없는데, 이유는 4.4절 참고.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/design/kangcheolung-`#148-ragops-dashboard-retry.md around lines 106 -
109, Replace the internal labels 이슈1 and 이슈2 in the documented retry flow with
the identified issue references `#134` and `#137`, respectively, while preserving
the existing service and method references.

Source: Coding guidelines

@kangcheolung
kangcheolung merged commit 601552d into develop Aug 11, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feat] RAGOps Dashboard 관리자 재처리 API

1 participant