TransferManager::uploadFile | response path: /tmp/workspace/675912/alignments_all.json, code: 503, m
RCA: TransferManager::uploadFile | S3 503 Slow Down
Error Log#
TransferManager::uploadFile | response path: /tmp/workspace/675912/alignments_all.json, code: 503, message: Slow Down
Impact#
- Service:
cupixworks-capture-postprocessor-agent - Team: southlandind
- 발생 횟수: 1 (이 클러스터), 7+ (최근 1주간 동일 패턴)
- 최초 발생: 2026-04-06T21:41:03.045Z
- 최근 발생: 2026-04-06T21:41:03.045Z
Root Cause Summary#
AWS S3가 요청 속도 제한(rate limiting)으로 인해 HTTP 503 "Slow Down" 응답을 반환했으며, TransferManager::uploadFile은 이 응답을 받으면 즉시 에러로 처리하고 reject한다. uploadFile이 직접 호출될 때(task queue를 거치지 않고 PostprocessorService::uploadAlignmentData에서 직접 await하는 경우)에는 retryTask 로직이 적용되지 않아 재시도 없이 실패한다. 이후 uploadAlignmentData의 catch 블록이 이 에러를 warn 레벨로만 로깅하고 삼켜버려, alignment 데이터 업로드가 조용히 누락된다. 최근 1주간 여러 리전(us-east-1, us-west-1, us-west-2)에서 동일한 S3 503 Slow Down 패턴이 반복 발생하고 있어, 이는 일시적 S3 스로틀링이 아니라 구조적인 재시도 미비 문제이다.
Technical Analysis#
Code Path#
- Entry point:
postprocessor-service.ts:105—await this.uploadAlignmentData(cpCapture)호출 uploadAlignmentData는 Tesla API에서 presigned URL을 받아transferManager.uploadFile()을 직접await로 호출한다 (postprocessor-service.ts:202).uploadFile(transfer.manager.ts:81-107) 내부에서request.put()으로 S3에 PUT 요청을 보낸다.- S3가 503 응답을 반환하면,
sendReq.on('response')핸들러(transfer.manager.ts:93-101)에서statusCode !== 200이므로reject()된다. uploadAlignmentData의catch블록(postprocessor-service.ts:214-216)이 에러를 warn으로 로깅하고 종료 — 재시도 없음, 에러 전파 없음.
핵심 문제 1 — 직접 호출 시 재시도 없음:
uploadFile이 task queue가 아닌 직접 호출로 사용될 때, retryTask 메커니즘이 적용되지 않는다. task queue의 transferTask → retryTask 경로(transfer.manager.ts:193-214)만 retry를 지원한다.
// postprocessor-service.ts:201-206 — 직접 호출, retry 없음
if (allResultsResource && allResultsResource.upload_url) {
await this.transferManager.uploadFile(
allResultsResource.upload_url,
allResultsFilePath,
{}
);
// transfer.manager.ts:81-107 — 503 시 즉시 reject
uploadFile = (url: string, path: string, headers: any): Promise<void> => new Promise((resolve, reject) => {
// ...
sendReq
.on('response', async res => {
if (res.statusCode === 200) {
// ...
resolve();
} else {
logger.error('TransferManager::uploadFile | response path: %s, code: %d, message: %s', path, res.statusCode, res.statusMessage);
reject(this.cupixAuth.handleError(res));
}
})
핵심 문제 2 — 에러를 삼키는 catch 블록:
// postprocessor-service.ts:214-216 — 에러를 warn으로만 기록하고 삼킴
} catch (error) {
logger.warn('PostprocessorService::uploadAlignmentData | end - %s', JSON.stringify(error));
}
기대 동작: S3 503은 일시적 스로틀링이므로 exponential backoff로 재시도 후 업로드 완료되어야 한다. 실제 동작: 재시도 없이 즉시 실패하고, alignment 데이터 업로드가 누락된다.
핵심 문제 3 — checkStatusCode 로직의 범위 오류:
// transfer.manager.ts:168-171
private checkStatusCode = (error: any): boolean => {
if (error?.statusCode != undefined && error.statusCode > 400 && error.statusCode < 500) return false;
return true;
};
이 메서드는 400-499(4xx) 에러만 재시도 불가로 판단한다. 503은 이 범위 밖이므로 retry 대상이지만, task queue 경로에서만 retryTask가 호출되므로 직접 호출 시에는 의미가 없다.
Log Evidence#
사용한 Datadog 쿼리:
service:cupixworks-capture-postprocessor-agent status:error "TransferManager"
Time range: 2026-04-06T20:00:00Z to 2026-04-06T23:00:00Z
service:cupixworks-capture-postprocessor-agent "503" OR "Slow Down"
Time range: 2026-04-01T00:00:00Z to 2026-04-07T00:00:00Z
이벤트 타임라인 (workspace 675912):
| Timestamp (KST) | Level | Message |
|---|---|---|
| 2026-04-07 06:41:03 | error | TransferManager::uploadFile | response path: /tmp/workspace/675912/alignments_all.json, code: 503, message: Slow Down |
| 2026-04-07 06:41:03 | warn | CupixAuth::handleError | Undefined response: {"statusCode":503,"request":{"method":"PUT"}} |
| 2026-04-07 06:41:03 | warn | PostprocessorService::uploadAlignmentData | end - {"statusCode":503,...,"server":"AmazonS3"} |
| 2026-04-07 06:41:12 | info | BaseService::cleanUpAnythingRelatedModel | path: /tmp/workspace/675912 |
| 2026-04-07 06:41:13 | info | BaseService::cleanUpAnythingRelatedModel | path: /tmp/workspace/675912 |
에러 발생 후 ~9초 만에 workspace cleanup이 진행되었다. 이는 uploadAlignmentData가 에러를 삼킨 후 후속 작업이 정상 진행된 것을 의미한다.
S3 응답 상세 (원문):
{
"statusCode": 503,
"headers": {
"x-amz-request-id": "8ACMRBQWQ6J4XDDD",
"server": "AmazonS3"
},
"request": {
"uri": {
"hostname": "s3.amazonaws.com",
"pathname": "/cupixworks-source-dc9dcff32488-usea1/resources/6yllrt/usea1/v1"
},
"method": "PUT",
"headers": {
"Content-Length": 4092175,
"content-type": "application/json"
}
}
}
최근 1주 동일 패턴 (7건 이상 확인):
| Date (KST) | Workspace | File | Region | Size |
|---|---|---|---|---|
| 2026-04-07 06:41 | 675912 | alignments_all.json | us-east-1 | 4MB |
| 2026-04-04 07:35 | 675109 | process_output.zip | us-west-2 | 124MB |
| 2026-04-04 05:44 | 675124 | process_output.zip | us-west-1 | 23MB |
| 2026-04-04 04:06 | 674892 | process_output.zip | us-east-1 | 174MB |
| 2026-04-03 08:32 | 673435 | process_output.zip | us-west-1 | 147MB |
| 2026-04-02 08:40 | 674059 | process_output.zip | us-west-2 | 56MB |
| 2026-04-02 05:41 | 673932 | process_output.zip | us-east-1 | 150MB |
여러 리전과 버킷에서 발생하므로, 단일 버킷 이슈가 아닌 요청 패턴에 의한 S3 스로틀링이다.
Fix Recommendation#
즉시 조치 (Critical)#
postprocessor-service.ts:167-217:uploadAlignmentData에서this.transferManager.uploadFile()직접 호출 대신 exponential backoff가 포함된 retry wrapper를 적용해야 한다. S3 503은 일시적이므로 3-5회 재시도(1s, 2s, 4s 간격)면 대부분 해결된다.postprocessor-service.ts:214-216: catch 블록이 에러를 삼키지 않고 상위로 전파하거나, 최소한 retry 실패 후에만 warn으로 로깅하도록 변경해야 한다. 현재는 alignment 데이터 누락이 무시되어 데이터 정합성 문제가 발생할 수 있다.
단기 개선 (1주 이내)#
uploadFile메서드(transfer.manager.ts:81-107) 자체에 5xx 응답에 대한 retry 로직을 내장해야 한다. 현재 task queue 경로에서만 retry가 동작하는 이중 구조는 직접 호출 시 취약점이 된다.- 동일한 패턴이
uploadProcessOutput(postprocessor-service.ts:250-274)에서도 발생하고 있으므로 함께 수정해야 한다 (로그 증거: 최근 1주간process_output.zip업로드 실패 다수).
장기 개선 (재발 방지)#
- S3 업로드를 AWS SDK v3의
@aws-sdk/lib-storage로 마이그레이션하면 multipart upload + 내장 retry + exponential backoff를 모두 지원한다. 현재request라이브러리(deprecated) 기반의 직접 PUT은 대용량 파일(100MB+) 업로드에 비효율적이며 스로틀링에 취약하다. - 모든 직접
uploadFile호출 지점을 task queue 경로로 통일하여 retry 로직의 일관성을 확보해야 한다.
Monitoring#
- S3 503 발생 빈도 추적:
service:cupixworks-capture-postprocessor-agent status:error "code: 503"
- alignment 데이터 업로드 실패 추적:
service:cupixworks-capture-postprocessor-agent status:warn "uploadAlignmentData"
- S3 요청 메트릭 (CloudWatch):
aws.s3.5xx_errors{bucket:cupixworks-source-*}
Risk Assessment#
- Risk level: medium
- 예상 복잡도: standard — retry wrapper 추가는 비교적 단순하지만, 모든 직접 호출 지점을 파악하고 일관되게 적용해야 한다. alignment 데이터 누락이 downstream 처리에 미치는 영향은 추가 확인이 필요하다.