배경
문서 인덱싱 성공 경로는 Attempt·Job·Version·Document를 원자적으로 INDEXED로 전환한다. 반면 파싱, Embedding 생성 또는 완료 단계에서 오류가 발생하면 Attempt와 Job이 STARTED/PROCESSING에 남으며, 이미 준비된 retry_count, max_retry_count, 오류 필드와 실패·재시도 이벤트가 실제 전이에 사용되지 않는다.
현재 Claim을 소유한 Worker가 실패를 명시적으로 보고하면 Attempt를 종료하고, 서버가 실패 유형과 남은 횟수를 기준으로 지연 재시도 또는 최종 실패를 결정한다.
목표
- Worker·Claim Token·Lease·Attempt를 검증하는 실패 종료 API 제공
- Attempt를 오류 원인과 함께
FAILED로 종료
- 재시도 가능한 실패는 Job을 실행 가능 시각이 지정된
PENDING으로 복귀
- 영구 실패 또는 재시도 소진 시 Job·Version을 최종
FAILED로 종료
- 새 Version 실패 시 기존 검색 가능한 current Version과 Document의
INDEXED 상태 유지
- 검색 가능한 Version이 없는 최종 실패 시 Document를
FAILED로 전환
- 동일 실패 요청의 멱등 재생과 완료 요청과의 동시성 안전성 보장
- 실패·재시도 상태와 이벤트를 하나의 Transaction으로 저장
API 초안
POST /admin/indexing-jobs/{jobId}/attempts/{attemptId}/fail
{
"workerId": 7,
"claimToken": "34c19d16-6ae1-4f6a-a35d-0123456789ab",
"failureType": "EMBEDDING_PROVIDER_UNAVAILABLE",
"errorMessage": "Embedding provider request timed out"
}
Worker가 retryable을 직접 결정하지 않고 서버가 제한된 failureType별 정책으로 판정한다.
| failureType |
재시도 |
STORAGE_UNAVAILABLE |
가능 |
DOCUMENT_CONTENT_INVALID |
불가 |
EMBEDDING_PROVIDER_UNAVAILABLE |
가능 |
EMBEDDING_RESULT_INVALID |
불가 |
INDEXING_STATE_INCONSISTENT |
불가 |
WORKER_INTERNAL_ERROR |
가능 |
최초 처리와 동일 요청 재전송은 모두 200 OK를 반환한다. 응답은 이후 Job 변경과 무관하게 재생할 수 있도록 Attempt의 고정된 실패 결과만 포함한다.
상태 전이
재시도
- Attempt:
STARTED -> FAILED
- Job:
PROCESSING -> PENDING
- Version: 현재 처리 단계 유지
- Document: 변경 없음
retry_count 증가 및 next_retry_at 계산
- Worker·Claim Token·Lease 해제
- 최근 오류 Snapshot 저장
- 단계별 실패 이벤트와
RETRY 이벤트 저장
Version 상태를 유지해 다음 Claim이 기존 멱등 처리 규칙으로 재개한다.
PARSING + Chunk 없음: 파싱 재개
EMBEDDING + Embedding 없음: Embedding 재실행
EMBEDDING + 전체 Embedding 존재: 저장 결과 재생 후 완료
최종 실패
- Attempt:
STARTED -> FAILED
- Job:
PROCESSING -> FAILED
- Version: 현재 처리 단계
-> FAILED
- 검색 가능한 current Version이 없으면 Document
-> FAILED
- 기존 current Version이
INDEXED이면 Document와 포인터 유지
- 실패 Version의
ACTIVE Embedding은 STALE 처리
- 단계별 실패 이벤트와
FAILED 이벤트 저장
재시도 정책
max_retry_count = 3은 최초 실행 이후 최대 3회 재시도로 정의하며 최대 Attempt 수는 4회다.
- 첫 재시도: 10초
- 두 번째 재시도: 20초
- 세 번째 재시도: 40초
- 최대 지연: 5분
embedding_jobs.next_retry_at을 추가하고 Claim 후보를 다음과 같이 제한한다.
status = 'PENDING'
AND (next_retry_at IS NULL OR next_retry_at <= :claimedAt)
별도 Scheduler 없이 기존 Claim API가 실행 가능 시각이 지난 Job을 선택한다.
Transaction 및 잠금
- Job 쓰기 잠금
- 기존 FAILED Attempt 멱등 재생 여부 확인
- Worker·Claim Token·Lease 검증
- Attempt 실행 Context 검증
- Version 쓰기 잠금
- Document 쓰기 잠금
- 재시도 또는 최종 실패 상태 전이
- Embedding 상태 정리와 이벤트 저장
- Commit
완료 흐름과 동일하게 Job -> Version -> Document 잠금 순서를 사용한다. 완료와 실패가 경쟁하면 먼저 Job 잠금을 획득해 커밋한 한쪽만 성공한다.
멱등성
이미 FAILED인 동일 Attempt에 같은 Worker·Claim Token·실패 유형·오류 메시지로 재요청하면 저장된 실패 결과를 반환한다.
재생 시 Retry 횟수와 실행 시각을 다시 계산하거나 상태·이벤트·실패 시각을 변경하지 않는다. 동일 Attempt를 다른 실패 내용으로 종료하려 하면 409 Conflict로 거부한다.
제외 범위
- Lease 연장 API
- 만료 Lease 자동 회수
- DEAD Worker Job 복구
- Worker 자동 Polling Loop
- 관리자 수동 재시도·취소 API
- 부분 Chunk·Embedding 삭제 도구
- Retry Jitter와 실패 Dashboard
Lease가 이미 만료됐거나 Worker가 죽어 실패 API를 호출하지 못한 Job의 복구는 후속 작업에서 다룬다.
완료 조건
배경
문서 인덱싱 성공 경로는 Attempt·Job·Version·Document를 원자적으로
INDEXED로 전환한다. 반면 파싱, Embedding 생성 또는 완료 단계에서 오류가 발생하면 Attempt와 Job이STARTED/PROCESSING에 남으며, 이미 준비된retry_count,max_retry_count, 오류 필드와 실패·재시도 이벤트가 실제 전이에 사용되지 않는다.현재 Claim을 소유한 Worker가 실패를 명시적으로 보고하면 Attempt를 종료하고, 서버가 실패 유형과 남은 횟수를 기준으로 지연 재시도 또는 최종 실패를 결정한다.
목표
FAILED로 종료PENDING으로 복귀FAILED로 종료INDEXED상태 유지FAILED로 전환API 초안
{ "workerId": 7, "claimToken": "34c19d16-6ae1-4f6a-a35d-0123456789ab", "failureType": "EMBEDDING_PROVIDER_UNAVAILABLE", "errorMessage": "Embedding provider request timed out" }Worker가
retryable을 직접 결정하지 않고 서버가 제한된failureType별 정책으로 판정한다.STORAGE_UNAVAILABLEDOCUMENT_CONTENT_INVALIDEMBEDDING_PROVIDER_UNAVAILABLEEMBEDDING_RESULT_INVALIDINDEXING_STATE_INCONSISTENTWORKER_INTERNAL_ERROR최초 처리와 동일 요청 재전송은 모두
200 OK를 반환한다. 응답은 이후 Job 변경과 무관하게 재생할 수 있도록 Attempt의 고정된 실패 결과만 포함한다.상태 전이
재시도
STARTED -> FAILEDPROCESSING -> PENDINGretry_count증가 및next_retry_at계산RETRY이벤트 저장Version 상태를 유지해 다음 Claim이 기존 멱등 처리 규칙으로 재개한다.
PARSING+ Chunk 없음: 파싱 재개EMBEDDING+ Embedding 없음: Embedding 재실행EMBEDDING+ 전체 Embedding 존재: 저장 결과 재생 후 완료최종 실패
STARTED -> FAILEDPROCESSING -> FAILED-> FAILED-> FAILEDINDEXED이면 Document와 포인터 유지ACTIVEEmbedding은STALE처리FAILED이벤트 저장재시도 정책
max_retry_count = 3은 최초 실행 이후 최대 3회 재시도로 정의하며 최대 Attempt 수는 4회다.embedding_jobs.next_retry_at을 추가하고 Claim 후보를 다음과 같이 제한한다.별도 Scheduler 없이 기존 Claim API가 실행 가능 시각이 지난 Job을 선택한다.
Transaction 및 잠금
완료 흐름과 동일하게
Job -> Version -> Document잠금 순서를 사용한다. 완료와 실패가 경쟁하면 먼저 Job 잠금을 획득해 커밋한 한쪽만 성공한다.멱등성
이미
FAILED인 동일 Attempt에 같은 Worker·Claim Token·실패 유형·오류 메시지로 재요청하면 저장된 실패 결과를 반환한다.재생 시 Retry 횟수와 실행 시각을 다시 계산하거나 상태·이벤트·실패 시각을 변경하지 않는다. 동일 Attempt를 다른 실패 내용으로 종료하려 하면
409 Conflict로 거부한다.제외 범위
Lease가 이미 만료됐거나 Worker가 죽어 실패 API를 호출하지 못한 Job의 복구는 후속 작업에서 다룬다.
완료 조건
PENDING으로 복귀시킨다.