fix(db): Workers에서 postgres/mysql 연결을 요청당 생성·해제 — 로그인 hang 수정 - #71
Merged
Conversation
프로덕션(idp.hyochan.site)에서 POST /login 이 Worker hang → 500 으로
취소되는 문제 수정. D1→PostgreSQL(Hyperdrive) 전환 후 발생.
근본 원인: getDb 가 postgres/mysql 연결을 모듈 전역 싱글턴으로 캐시하고
닫지 않았다. Cloudflare Workers 는 I/O 객체(TCP 소켓)를 요청 간 공유할 수
없으므로, 첫 요청이 만든 소켓을 다음 invocation 이 재사용하다 죽은 소켓
I/O 에서 영원히 hang 한다. D1(요청별 바인딩)에선 드러나지 않던 결함.
- getDb 가 { db, dispose? }(DbHandle) 반환. platform.ctx.waitUntil 유무로
Workers 판별 — Workers 는 요청당 연결 생성 + dispose, Node(adapter-node)는
기존 전역 재사용 유지. mysql 은 Workers 에서 disableEval:true 추가.
sqlite(libSQL HTTP)/d1 은 소켓 장기점유가 없어 그대로.
- hooks.server.ts: 응답 후 ctx.waitUntil(dispose()) 로 요청당 연결 정리
(응답 지연 없음). 아울러 DB 초기화 게이트가 platform.env.DB(D1 전용)로
하드코딩돼 postgres 배포에서 초기화가 스킵될 수 있던 것을 방언 인식으로 교체.
Cloudflare Hyperdrive + postgres-js 권장 패턴(요청당 연결, max:5,
ctx.waitUntil(sql.end()))과 일치.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
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.
문제
프로덕션(
idp.hyochan.site)에서POST /login이 Worker hang → 500 으로 취소됩니다. D1 → PostgreSQL(Hyperdrive) 전환(#70) 이후 발생한 프로덕션 다운 이슈입니다.관측된 로그:
근본 원인
src/lib/server/db/index.ts의getDb가 postgres/mysql 연결을 모듈 전역 싱글턴(pgSql/mysqlPool)으로 캐시하고 닫지 않았습니다.Cloudflare Workers 는 I/O 객체(TCP 소켓)를 요청 간 공유할 수 없습니다. 첫 요청(GET
/login— 폼 렌더 성공)이 만든 소켓을 다음 invocation(POST)이 재사용하려다 죽은 소켓 I/O 에서 영원히 멈추고, Workers 런타임이 hang 을 감지해 요청을 취소합니다. D1(요청별 바인딩)에선 드러나지 않던 결함이라 전환 전엔 보이지 않았습니다.수정
src/lib/server/db/index.tsgetDb가{ db, dispose? }(DbHandle) 반환.platform.ctx.waitUntil유무로 Workers 판별 — Workers 는 요청당 연결 생성 +dispose, Node(adapter-node)는 기존 전역 재사용 유지. mysql 은 Workers 에서disableEval: true추가. sqlite(libSQL HTTP)/d1 은 소켓 장기점유가 없어 그대로.src/hooks.server.tsctx.waitUntil(dispose())로 요청당 연결을 백그라운드에서 정리(응답 지연 없음). 아울러 DB 초기화 게이트가platform.env.DB(D1 전용)로 하드코딩돼 postgres 배포에서 초기화가 통째로 스킵될 수 있던 잠재 버그를 방언 인식 게이트로 교체.Cloudflare Hyperdrive + postgres-js 권장 패턴(요청당 연결,
max: 5,ctx.waitUntil(sql.end()))과 일치합니다.검증
DB_DIALECT=postgres tsc --noEmit— clean (exit 0)DB_DIALECT=postgres bun run build— clean (adapter-cloudflare, exit 0)prettier --check+eslint— clean🤖 Generated with Claude Code