Skip to content

[Feat] 인덱싱 Job Lease 갱신 및 만료 복구 - #91

Merged
Gimini-3 merged 8 commits into
developfrom
feature/90
Aug 3, 2026
Merged

[Feat] 인덱싱 Job Lease 갱신 및 만료 복구#91
Gimini-3 merged 8 commits into
developfrom
feature/90

Conversation

@Gimini-3

@Gimini-3 Gimini-3 commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

배경

Worker가 Claim 이후 비정상 종료하거나 Lease가 만료되면 Embedding Job과 Attempt가 실행 상태에 남을
수 있습니다. 정상 Worker가 Lease를 갱신할 수 있게 하고, 만료된 Job은 여러 서버가 동시에 복구하더라도
한 번만 상태 전이하도록 복구 흐름이 필요했습니다.

변경 사항

  • 현재 Worker·Claim Token·Heartbeat를 검증하는 Lease 갱신 API를 추가했습니다.
  • Heartbeat가 만료된 Worker를 조건부로 DEAD 처리하고, 만료 Job 후보를 순서와 Batch 크기에 맞춰 조회합니다.
  • Job 행 잠금과 FOR UPDATE SKIP LOCKED를 사용해 완료·실패·갱신·복구 경쟁을 직렬화했습니다.
  • 협력적 실패와 Lease 만료 복구가 같은 Retry Backoff 및 최종 실패 정책을 사용하도록 전이 로직을 공통화했습니다.
  • 후보별 독립 Transaction과 Scheduler 예외 격리를 적용해 한 Job의 실패가 다른 복구를 막지 않게 했습니다.
  • 상세 설계와 실제 PostgreSQL 검증 결과를 문서화했습니다.

주요 동작

  • 유효한 Lease만 갱신하며 locked_at과 Claim Token은 유지합니다.
  • 만료 복구 시 현재 소유권과 Attempt 정합성을 잠금 안에서 다시 확인합니다.
  • Attempt가 없으면 가짜 Attempt를 만들지 않습니다.
  • Retry가 남으면 소유권을 해제하고 PENDING으로 복귀합니다.
  • Retry를 소진하면 Version·Document·Embedding 정책과 함께 최종 실패 처리합니다.
  • 여러 Scheduler가 같은 Job을 선택해도 하나의 상태 전이만 Commit됩니다.

검증

  • ./gradlew clean build: 547개 테스트 통과, 실패·오류·Skip 0개
  • EmbeddingJobLeaseRecoveryIntegrationTest: 동시성 테스트 4개 통과
    • 만료 후보 정렬 및 제한 조회
    • 동일 Job 동시 복구의 단일 상태 전이
    • Attempt 부재 시 합성 방지
    • Retry 소진 시 최종 실패
  • 격리된 PostgreSQL 14(OpenSQL 호환) + pgvector 환경에서 검증했습니다.

문서

  • docs/design/Gimini-3-#90-indexing-job-lease-recovery.md
  • docs/test-results/Gimini-3-#90-indexing-job-lease-recovery.md

Closes #90

Summary by CodeRabbit

  • 새 기능

    • 관리자가 인덱싱 작업의 Lease를 갱신할 수 있는 API를 추가했습니다.
    • 유효한 소유권과 Worker 상태를 검증해 안전한 Lease 갱신을 지원합니다.
    • 만료된 인덱싱 작업을 주기적으로 감지하고 자동 복구합니다.
    • 복구 가능한 작업은 재시도하며, 재시도 횟수 소진 시 최종 실패 처리합니다.
    • Heartbeat가 만료된 Worker를 자동으로 DEAD 상태로 전환합니다.
  • 문서 및 테스트

    • Lease 갱신·복구 정책과 운영 절차를 문서화했습니다.
    • 관련 기능의 단위·통합·HTTP 테스트를 추가했으며 전체 검증을 완료했습니다.

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6bf82722-7f71-47dd-80f3-6b0506bbcdcb

📥 Commits

Reviewing files that changed from the base of the PR and between 2512635 and e984953.

📒 Files selected for processing (29)
  • docs/design/Gimini-3-#90-indexing-job-lease-recovery.md
  • docs/test-results/Gimini-3-#90-indexing-job-lease-recovery.md
  • src/main/java/com/opensource/docgrid/domain/embedding/controller/IndexingJobAdminController.java
  • src/main/java/com/opensource/docgrid/domain/embedding/converter/EmbeddingJobConverter.java
  • src/main/java/com/opensource/docgrid/domain/embedding/dto/request/RenewEmbeddingJobLeaseRequest.java
  • src/main/java/com/opensource/docgrid/domain/embedding/dto/response/RenewedEmbeddingJobLeaseResponse.java
  • src/main/java/com/opensource/docgrid/domain/embedding/entity/EmbeddingJob.java
  • src/main/java/com/opensource/docgrid/domain/embedding/repository/EmbeddingJobRepository.java
  • src/main/java/com/opensource/docgrid/domain/embedding/service/command/DocumentIndexingFailureService.java
  • src/main/java/com/opensource/docgrid/domain/embedding/service/command/EmbeddingJobLeaseRecoveryService.java
  • src/main/java/com/opensource/docgrid/domain/embedding/service/command/EmbeddingJobLeaseService.java
  • src/main/java/com/opensource/docgrid/domain/embedding/service/command/IndexingFailureTransitionService.java
  • src/main/java/com/opensource/docgrid/domain/embedding/service/query/EmbeddingJobRecoveryQueryService.java
  • src/main/java/com/opensource/docgrid/domain/worker/config/IndexingWorkerProperties.java
  • src/main/java/com/opensource/docgrid/domain/worker/enums/IndexingEventType.java
  • src/main/java/com/opensource/docgrid/domain/worker/lifecycle/WorkerLeaseRecoveryScheduler.java
  • src/main/java/com/opensource/docgrid/domain/worker/repository/WorkerNodeRepository.java
  • src/main/java/com/opensource/docgrid/domain/worker/service/command/WorkerNodeCommandService.java
  • src/main/resources/application.yml
  • src/test/java/com/opensource/docgrid/domain/embedding/controller/IndexingJobAdminControllerTest.java
  • src/test/java/com/opensource/docgrid/domain/embedding/entity/EmbeddingJobTest.java
  • src/test/java/com/opensource/docgrid/domain/embedding/integration/EmbeddingJobLeaseRecoveryIntegrationTest.java
  • src/test/java/com/opensource/docgrid/domain/embedding/service/command/EmbeddingJobLeaseRecoveryServiceTest.java
  • src/test/java/com/opensource/docgrid/domain/embedding/service/command/EmbeddingJobLeaseServiceTest.java
  • src/test/java/com/opensource/docgrid/domain/embedding/service/query/EmbeddingJobRecoveryQueryServiceTest.java
  • src/test/java/com/opensource/docgrid/domain/worker/config/IndexingWorkerPropertiesTest.java
  • src/test/java/com/opensource/docgrid/domain/worker/lifecycle/WorkerLeaseRecoverySchedulerTest.java
  • src/test/java/com/opensource/docgrid/domain/worker/repository/WorkerNodeRepositoryTest.java
  • src/test/java/com/opensource/docgrid/domain/worker/service/command/WorkerNodeCommandServiceTest.java

📝 Walkthrough

Walkthrough

인덱싱 Job Lease 갱신 API와 만료 복구 흐름을 추가했다. Worker 상태를 DEAD로 fencing하고, 만료 Job을 잠금 경쟁으로 단일 복구한다. Retry와 최종 실패 전이를 공통 서비스로 통합했다. 관련 단위·통합·HTTP 테스트와 설계·검증 문서를 추가했다.

Changes

Lease lifecycle

Layer / File(s) Summary
Lease 갱신 API와 소유권 검증
src/main/java/com/opensource/docgrid/domain/embedding/controller/*, src/main/java/com/opensource/docgrid/domain/embedding/service/command/EmbeddingJobLeaseService.java, src/main/java/com/opensource/docgrid/domain/embedding/dto/*, src/test/java/com/opensource/docgrid/domain/embedding/controller/*, src/test/java/com/opensource/docgrid/domain/embedding/service/command/EmbeddingJobLeaseServiceTest.java
관리자 Endpoint가 Worker ID와 canonical UUID Claim Token을 검증한다. Job과 Worker를 잠근 뒤 소유권, Lease, Heartbeat 상태를 확인하고 Lease 만료 시각만 갱신한다.
만료 Job 복구와 실패 전이
src/main/java/com/opensource/docgrid/domain/embedding/repository/EmbeddingJobRepository.java, src/main/java/com/opensource/docgrid/domain/embedding/service/command/*Failure*, src/main/java/com/opensource/docgrid/domain/embedding/service/command/EmbeddingJobLeaseRecoveryService.java, src/test/java/com/opensource/docgrid/domain/embedding/{service, integration}/*
만료된 PROCESSING Job을 Snapshot으로 조회하고 FOR UPDATE SKIP LOCKED로 재검증한다. STARTED Attempt를 종료하거나 Attempt 없이 Job만 전이한다. Retry와 최종 실패 상태 및 이벤트 저장을 공통화한다.
Worker fencing과 복구 Scheduler
src/main/java/com/opensource/docgrid/domain/worker/{config,enums,lifecycle,repository,service}/, src/main/resources/application.yml, src/test/java/com/opensource/docgrid/domain/worker/*
Heartbeat가 만료된 ACTIVE 또는 IDLE Worker를 DEAD로 변경한다. Scheduler가 DEAD 확정 후 만료 Job을 배치 복구하며, 후보별 실패를 격리한다. 복구 주기와 배치 크기 설정을 추가했다.
설계와 검증 기록
docs/design/*, docs/test-results/*
Lease 경계, 잠금 순서, 보안 규칙, 동시성 규칙과 PostgreSQL 검증 결과를 기록했다.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Scheduler
  participant RecoveryQuery
  participant RecoveryService
  participant FailureTransition
  Scheduler->>RecoveryQuery: 만료 PROCESSING Job ID 조회
  RecoveryQuery-->>Scheduler: 후보 ID Snapshot
  Scheduler->>RecoveryService: 후보별 복구 실행
  RecoveryService->>FailureTransition: Retry 또는 최종 실패 전이
  FailureTransition-->>RecoveryService: 전이 후 Job 상태
Loading

Possibly related PRs

  • DocGrid/backend#89: 기존 실패 전이 로직을 재사용하고 공통 서비스로 분리한 연결이 있다.
  • DocGrid/backend#49: 동일한 EmbeddingJob Lease 및 소유권 모델을 확장한다.
  • DocGrid/backend#64: EmbeddingJobAttempt 생명주기와 Claim Token 검증을 기반으로 한다.

Suggested labels: ✨ Feature

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/90

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.

@Gimini-3
Gimini-3 marked this pull request as ready for review August 3, 2026 08:15
@Gimini-3
Gimini-3 merged commit 22e6ebf into develop Aug 3, 2026
1 check was pending
@Gimini-3 Gimini-3 self-assigned this Aug 3, 2026
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] 인덱싱 Job Lease 갱신 및 만료 복구

1 participant