Repository navigation
배포: Fly idle_timeout 상한(900초)에 맞춰 프록시 읽기 한도에 상한을 둔다 - #12
Closed
NiceTry3675 wants to merge 1 commit into
Closed
NiceTry3675 wants to merge 1 commit into
NiceTry3675 wants to merge 1 commit into
Conversation
Fly는 http_options.idle_timeout을 900초까지만 받아 2,100초 설정이 배포를 거부했다 (Idle timeout must be less than or equal to 900). edge를 읽기 한도에 맞출 수 없으니 반대로 읽기 한도를 edge에 맞춘다: 서버의 상류 읽기 한도는 출력 토큰 상한 × 30ms에 비례하되 HARNEST_PROXY_MAX_TIMEOUT(기본 780초)에서 멈추고, 브라우저 공유 경로 클라이언트도 같은 상한에 60초 여유를 더해 840초까지만 기다린다. 서버 504(780초) → 클라이언트 시간 초과(840초) → edge 단절(900초) 순서가 유지되어 재시도 금지·본인 키 권장 안내가 사용자에게 닿는다.
Owner
Author
|
main에 직접 푸시하기로 해서 닫습니다. |
There was a problem hiding this comment.
🟡 Changes recommended
새로 추가된 웹 테스트에서 fake timer가 복구되지 않는 문제 등(테스트 신뢰성/설정 드리프트)으로 CI 안정성과 유지보수성에 영향을 줄 수 있습니다.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Fly.io edge의 idle_timeout 상한(900초) 제약 때문에 배포가 실패한 문제를 해결하기 위해, shared-key 프록시 경로의 서버 상류(read) 타임아웃을 edge 한도 아래로 “상한” 처리하고, 웹 클라이언트도 그 상한(+60초)까지만 기다리도록 맞춘 PR입니다. 프록시 경로에서 서버 504 → 클라이언트 타임아웃 → edge 단절 순서를 보장해 사용자에게 안내가 도달하도록 하는 목적이 코드/문서/테스트에 반영돼 있습니다.
Changes:
fly.toml의idle_timeout을 Fly 허용 상한인 900초로 조정하고, 관련 운영 제약을 주석으로 정리- API 프록시 상류 읽기 한도에
HARNEST_PROXY_MAX_TIMEOUT(기본 780초) 상한을 추가하고 계산식을 상한 적용으로 변경 - 웹 shared 프록시 요청도 동일 상한(+60초)까지만 대기하도록 캡을 추가하고, SPEC/README/테스트를 갱신
File summaries
| File | Description |
|---|---|
| SPEC.md | shared-key 프록시의 “전송 계층 제한” 설명에 edge 유휴 한도 제약을 명시 |
| fly.toml | Fly edge idle_timeout을 900초로 낮추고 상류/클라이언트 타임아웃 상호관계를 주석으로 업데이트 |
| apps/web/src/lib/llm.ts | shared 프록시 요청 타임아웃을 780초 상한(+60초 마진)으로 캡핑 |
| apps/web/src/lib/llm.test.ts | shared 프록시 기본 타임아웃 상한(840초) 동작을 검증하는 테스트 추가 |
| apps/api/test_api.py | API 상류 read timeout 상한(780초) 동작을 테스트로 고정 |
| apps/api/README.md | Fly 상한 및 HARNEST_PROXY_MAX_TIMEOUT 도입에 따른 운영/설정 가이드 갱신 |
| apps/api/main.py | _upstream_read_timeout에 상한(HARNEST_PROXY_MAX_TIMEOUT)을 적용하도록 변경 |
Review details
- Files reviewed: 7/7 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+1599
to
+1621
| it("기본 한도는 서버 읽기 한도 상한(780초) + 60초에서 멈춘다 — edge 유휴 한도(900초)보다 먼저 끊지 않고, 출력 상한이 커도 그 이상 기다리지 않는다", async () => { | ||
| vi.useFakeTimers(); | ||
| const hanging = (init?: RequestInit) => | ||
| new Promise<Response>((_, reject) => { | ||
| init?.signal?.addEventListener("abort", () => | ||
| reject(new DOMException("The user aborted a request.", "AbortError")), | ||
| ); | ||
| }); | ||
| const fetchMock = vi.fn(async (_url: string, init?: RequestInit) => hanging(init)); | ||
| vi.stubGlobal("fetch", fetchMock); | ||
| // 64,000토큰 × 30ms = 1,920초 — 상한 없이는 edge(900초)가 먼저 끊어 시간 초과 안내가 닿지 않는다 | ||
| const assertion = expect( | ||
| createSharedOpenAIClient("gpt-5.6-sol", { apiBase: "http://api.test", retryBaseMs: 0 }).complete( | ||
| "생성", | ||
| { maxOutputTokens: 64_000 }, | ||
| ), | ||
| ).rejects.toThrow("OpenAI(공유) 요청 시간 초과 (840000ms)"); | ||
| await vi.advanceTimersByTimeAsync(839_999); | ||
| expect(fetchMock).toHaveBeenCalledTimes(1); | ||
| await vi.advanceTimersByTimeAsync(1); | ||
| await assertion; | ||
| expect(fetchMock).toHaveBeenCalledTimes(1); | ||
| }); |
Comment on lines
+71
to
+74
| // 서버의 읽기 한도 상한(apps/api HARNEST_PROXY_MAX_TIMEOUT 기본값) — 서버는 벤더 응답을 다 받은 | ||
| // 뒤에야 첫 바이트를 보내므로 배포 edge의 유휴 한도(Fly 최댓값 900초) 아래에 머물러야 한다. 클라이언트도 | ||
| // 같은 상한을 알아야 서버 504(상한 + 0초)와 edge 단절(900초)보다 늦게, 즉 상한 + 60초에 끊는다. | ||
| const SHARED_PROXY_TIMEOUT_CEILING_MS = 780_000; |
This branch was successfully deployed
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
원인
2026-09-03
Deploy API to Fly실행(#33744350356)이 실패했습니다.직전 커밋(5b0c997)이
fly.toml의idle_timeout을 2,100초로 올렸는데, Fly가 허용하는 최댓값은 900초입니다.해결
edge를 읽기 한도에 맞출 수 없으니 읽기 한도를 edge에 맞춥니다.
fly.toml:idle_timeout = 900(Fly 최댓값)apps/api/main.py: 상류 읽기 한도는 출력 토큰 상한 × 30ms에 비례하되HARNEST_PROXY_MAX_TIMEOUT(기본 780초)에서 멈춤apps/web/src/lib/llm.ts: 공유 경로 클라이언트도 같은 상한 + 60초(840초)까지만 대기영향
공유 키 경로에서 13분을 넘기는 생성은 504로 끝납니다(약 26,000토큰 분량 기준). 그보다 긴 생성은 본인 키 직행 경로를 써야 합니다. 본인 키 경로는 변경 없음.
검증
cd apps/api && python3 test_api.py통과npm run typecheck통과npx vitest run apps/web/src/lib/llm.test.ts106개 통과