fix(db): OSIV 를 끈다 — SSE 스트림이 커넥션을 5분씩 쥐고 있었다 - #313
Merged
Conversation
#312 의 누수 탐지가 범인을 이름으로 찍었다(2026-09-08 07:09 dev): Connection leak detection triggered for com.mysql.cj.jdbc.ConnectionImpl@... at TaskStore.getOwned(...) at AgentEventStreamService.open(AgentEventStreamService.java:31) at AgentController.streamTaskEvents(AgentController.java:205) open-in-view 는 EntityManager(따라서 JDBC 커넥션)를 요청이 끝날 때까지 붙들어 둔다. 일반 REST 요청은 수십 ms 라 티가 안 나지만, SSE 요청의 수명은 스트림 수명이다 — STREAM_TIMEOUT_MS 가 5분이므로 커넥션 하나가 5분씩 묶인다. 스트림이 여러 개 열리면 (브라우저 탭·재연결·다중 사용자) 그만큼 풀이 마른다. 이것이 앞서 조사한 풀 고갈의 근본 원인이다. 01:52 부터 22분간 "Connection is not available (total=10, active=10, idle=0)" 이 이어지고 재기동으로만 풀렸던 것, 첫 희생자가 agent-event 스레드였던 것, 그 사이 auth/refresh 와 approvals 가 500 을 내고 스케줄 워커가 전부 실패했던 것이 한 줄기로 설명된다. 스프링이 기동 때마다 경고를 남기고 있었는데(JpaWebConfiguration: "open-in-view is enabled by default") 아무도 안 봤다. 끄는 것이 안전한 이유: 이 프로젝트는 JPA 연관관계를 하나도 쓰지 않는다(@manytoone · @onetomany · @OnetoOne · @manytomany 전부 0건). 엔티티는 전부 toDomain() 으로 도메인 객체에 옮겨 담아 나가므로(25개 매퍼) 트랜잭션 밖에서 지연 로딩될 대상 자체가 없다. #312(풀 20 · 누수 탐지)는 그대로 둔다. 그건 완화이자 진단 장치이고, 이번처럼 다음 누수도 이름으로 잡아 준다. 검증: 전체 1326개 통과. dev 배포 후 SSE 를 실제로 열어 leak detection WARN 이 사라지는지 확인 필요. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013y8USoCXTsRTATAhy88M93
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.
누수 탐지가 찍은 것 (dev, 07:09)
원인
open-in-view는 EntityManager(따라서 JDBC 커넥션)를 요청이 끝날 때까지 붙들어 둔다. 일반 REST 요청은 수십 ms 라 티가 안 나지만, SSE 요청의 수명은 스트림 수명이다 —STREAM_TIMEOUT_MS가 5분이므로 커넥션 하나가 5분씩 묶인다.스트림이 여러 개 열리면(브라우저 탭 · 재연결 · 다중 사용자) 그만큼 풀이 마른다.
앞선 조사가 한 줄기로 설명된다
이것이
auth/refresh500 조사에서 만난 풀 고갈의 근본 원인이다:Connection is not available (total=10, active=10, idle=0)이 이어지고 재기동으로만 풀림 → 스트림이 계속 다시 열리니 재기동 전에는 안 풀린다agent-event스레드 → 스트림 자신이 가장 먼저 굶는다auth/refresh·approvals가 500, 스케줄 워커 전부 실패 → DB 커넥션이 필요한 모든 것이 함께 죽는다스프링이 기동 때마다 경고를 남기고 있었다. 아무도 안 봤다:
끄는 것이 안전한 이유
이 프로젝트는 JPA 연관관계를 하나도 쓰지 않는다.
엔티티는 전부
toDomain()으로 도메인 객체에 옮겨 담아 나간다(매퍼 25개). 트랜잭션 밖에서 지연 로딩될 대상 자체가 없다.#312 는 그대로 둔다
풀 20 · 누수 탐지는 완화이자 진단 장치다. 이번처럼 다음 누수도 이름으로 잡아 준다 — 그게 이 수정을 가능하게 한 것이기도 하다.
검증
전체 1326개 통과. dev 배포 후 SSE 를 실제로 열어 leak detection WARN 이 사라지는지 확인 필요.
🤖 Generated with Claude Code
https://claude.ai/code/session_013y8USoCXTsRTATAhy88M93