The keycloak project ended with four open questions that design could not
settle. A two-VM lab was built to answer them by measurement, and this is
that material: 26 experiments, 125 raw command outputs, 22 browser captures.
Follows the import procedure in README.md.
source/ the originating repository verbatim — 78 documents, 28 SVGs,
8 manifests, plus .source-revision recording the commit
final/ the SSOT
document.md 729 lines written from the 29 experiment documents, not
concatenated: what was predicted, what was measured, and
where the measurement itself was wrong
evidence/raw 125 outputs, flattened to <experiment>__<file> because
the originals collided (01-baseline.txt appeared three
times) and the audit only globs the top level
evidence/meta one per raw file; command and exitCode are null and the
README says why rather than inventing them
evidence/browser 22 captures
assets/ three diagrams through techviz
.techviz/ their VizSpecs
A separate project rather than an addition to keycloak: the B-layer answers
that project's four questions, but the A, C and D layers are about cluster
failure, SSO and operations, and one document.md should hold one subject.
The four question records there can point here through 관계.
Recorded rather than papered over: only three of the 28 diagrams were
remade. The repository forbids hand-drawn SVG and forbids titles inside the
canvas; all 28 originals carry both, so converting them is redrawing, not
reformatting. They stay in source/ and the gap is written into the document.
verify-pipeline.py passes. audit-records.py reports no issues.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
177 lines
20 KiB
Markdown
177 lines
20 KiB
Markdown
---
|
|
kind: CASE
|
|
slug: analysis-finding-a06-f004
|
|
title: 전용 category 를 붙이는 유일한 분기가 도달할 수 없다
|
|
topic: multitenancy-isolation
|
|
project: clean-architecture-backend-template
|
|
status: 게시 전
|
|
sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
|
|
rootTreeNode: case:analysis-finding-a06-f004
|
|
evidenceCapturedOn: 2026-09-04
|
|
body: case-analysis-finding-a06-f004.body.md
|
|
assets:
|
|
- key: analysis-finding-a06-f004
|
|
file: ../../../final/evidence/rendered/analysis-finding-a06-f004.svg
|
|
evidence:
|
|
- ../../../final/evidence/raw/analysis-finding-a06-f004.txt
|
|
source:
|
|
- 원본 분석 절은 analysis/06-adapter-outbound-persistence-mongo.md §16 이다.
|
|
---
|
|
|
|
# 전용 category 를 붙이는 유일한 분기가 도달할 수 없다
|
|
|
|
`MongoFailureCategory:68` 에 `SCHEMA_VERSION_UNSUPPORTED` 가 있고 `MongoDataSchemaUnsupportedException:42`~`:53` 이 세 버전을 공개 접근자로 노출한다. 그 값을 쓰는 자리는 저장소 전체에 열거형 선언과 `DefaultMongoFailureTranslator:110` 의 `case` 둘뿐인데, 분류기가 그 값을 만들지 않으므로 그 `case` 는 돌지 않는다.
|
|
|
|
## 관계
|
|
|
|
- **모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다**
|
|
그 규칙은 한번 접힌 정보가 복구되지 않는다고 적는다. 여기서는 스키마 버전 거절이 `OPERATION_REJECTED` 로 접혀 다른 로컬 거절과 구별되지 않는다.
|
|
- **위험한 조합은 정책이 아니라 생성자가 거부하게 만든다**
|
|
그 규칙대로면 버전을 모르는 예외는 만들어질 수 없어야 한다. `MongoDataSchemaUnsupportedException` 의 생성자는 `-1` 셋을 그대로 받고, `DefaultMongoFailureTranslator:111` 이 그 값으로 예외를 만든다.
|
|
- **중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다**
|
|
같은 예외를 만드는 자리가 둘인데 조립 상태가 반대다. `DefaultMongoFailureTranslator` 는 `MongoPlatformAutoConfiguration:93` 이 빈으로 만들지만 그 `case` 가 실행되지 않고, `MongoSchemaVersionPolicy` 는 값을 아는 쪽인데 `new` 를 부르는 main 줄이 0 이다.
|
|
|
|
## 문제
|
|
|
|
이 실패에는 열거형 값 하나와 예외 타입 하나가 따로 마련돼 있다. 예외는 세 정수를 접근자로 내주므로 분기할 범주와 진단할 값을 함께 줄 수 있다.
|
|
|
|
그 어휘가 실제로 쓰이는지 확인했다.
|
|
|
|
## 결론
|
|
|
|
MongoFailureCategory:3~:9 는 이 값이 메트릭과 대시보드에 나타난다고 적는다. 그래서 알 수 없는 서버 코드는 새 범주를 만드는 대신 UNCLASSIFIED 로 간다.
|
|
|
|
new MongoDataSchemaUnsupportedException 을 부르는 main 자리는 둘이다.
|
|
|
|
MongoSchemaVersionPolicy:85 가 실제 버전 값 셋을 넘긴다. version.value() 와 range.minimumSupported().value() 와 range.current().value() 다.
|
|
|
|
그런데 그 예외가 들고 가는 context 는 :84 의 MongoFailureContext.rejected(...) 가 만든 것이다. MongoFailureContext:135~:148 이 그 안에 OPERATION_REJECTED 와 NOT_SENT 를 박는다. 전용 범주가 아니라 로컬 거절 범주다.
|
|
|
|
DefaultMongoFailureTranslator:111 이 전용 범주를 붙이는 유일한 자리인데 세 값 모두 -1 이다.
|
|
|
|
그런데 그 분기에 들어올 값이 없다. SCHEMA_VERSION_UNSUPPORTED 라는 이름이 저장소 전체에 두 줄만 있고 그 둘이 방금 인용한 선언과 case 이므로, 그 값을 컨텍스트에 넣는 코드가 존재하지 않는다. 같은 검색을 OPERATION_REJECTED 로 걸면 넷이 나온다.
|
|
|
|
분류기가 범주를 정하는 자리는 DefaultMongoFailureClassifier 안에 여럿이다. :88~:96 이 드라이버 라벨을 먼저 보고, :99 와 :106~:109 와 :112 가 단계와 결과에 따라 고르며, 마지막이 :156 의 CATEGORY_BY_CODE 조회다. 어느 자리에서도 이 범주가 나오지 않는다.
|
|
|
|
그래서 SCHEMA_VERSION_UNSUPPORTED 로 집계되는 실패가 생기지 않는다. 다른 범주로 새는 것도 아직 없다. new MongoSchemaVersionPolicy 를 부르는 main 줄이 0 이고 그 이름이 main 에 나오는 자리가 자기 선언 셋뿐이라, 이 리비전에서는 그 예외를 던지는 코드가 돌지 않는다. 시험만 여섯 번 만든다.
|
|
|
|
MongoSchemaVersionPolicyTest 가 그 어긋남을 잡지 못한다. 시험 여섯이 전부 던져진 타입이나 반환값만 보고, 범주와 세 접근자를 확인하는 줄이 하나도 없다.
|
|
|
|
그래서 이 결함은 채택자가 정책을 배선하는 순간에 드러난다. 전용 칸이 비어 있는 채로 거절만 다른 칸에 쌓이기 시작한다.
|
|
|
|
이 모듈에 살아 있는 다른 스키마 실패 경로는 세 번째 범주를 쓴다. MongoFailureContext.schemaMismatch:157 이 SCHEMA_VALIDATION 과 NO_WRITE_PERFORMED 를 박고, PolicyAwareMongoTypeMapper:112·:185·:192 가 그것을 부른다. 저장된 문서가 이 릴리스가 기대하는 스키마와 맞지 않을 때 실제로 도는 것이 그 경로다.
|
|
|
|
-1 을 채워 넣는 자리가 하나 더 있다. DefaultMongoFailureTranslator:106 의 MongoDocumentTooLargeException 인데, 이쪽은 서버 코드 10334 와 17420 이 그 범주로 매핑돼 있어 실제로 만들어진다. 접근자 계약에 값이 없을 수 있다는 말이 없는 것만 남는다.
|
|
|
|
## 검증 환경
|
|
|
|
OpenJDK : 21.0.12
|
|
확인 방식 : 범주 열거형의 클래스 자바독과 두 상수 인용, 전용 예외 전문 인용, 프로덕션 생성 지점 전수, 정책이 만드는 context 와 그 팩터리가 박는 값 인용, translator 의 switch 전문 인용, 전용 범주가 나오는 줄의 저장소 전체 계수와 대조 계수, 분류기가 범주를 정하는 자리 전부 인용, 같은 모듈의 다른 스키마 실패 팩터리와 그 호출자 인용, 두 생성 지점의 조립 계수와 대조, 정책 시험의 단언 전수와 접근자 단언 계수와 대조
|
|
소스 수정 : x
|
|
|
|
## 재현 조건
|
|
|
|
1. 범주 열거형의 클래스 자바독과 이 값의 주석을 인용한다.
|
|
2. 전용 예외의 자바독과 세 접근자를 인용한다.
|
|
3. new MongoDataSchemaUnsupportedException 을 부르는 main 자리를 전부 찾는다.
|
|
4. 정책이 만드는 context 와 그 팩터리 메서드 본문을 인용한다.
|
|
5. translator 의 switch 를 전문으로 싣는다.
|
|
6. 전용 범주가 저장소 전체에 몇 줄 나오는지 세고, 다른 범주 이름으로 같은 검색을 건다.
|
|
7. 분류기가 범주를 정하는 자리를 전부 인용하고, 같은 모듈의 다른 스키마 실패 팩터리와 그 호출자를 함께 싣는다.
|
|
8. 정책 시험의 단언을 전부 뽑고 접근자를 단언하는 줄을 센다.
|
|
|
|
## 본문
|
|
|
|
<!-- body:start -->
|
|
|
|
`MongoFailureCategory` 는 실패의 안정된 부모 범주다. 스키마 버전 실패를 위한 값이 그 안에 있다.
|
|
|
|
## 이 실패에 마련된 값과 타입
|
|
|
|
:::evidence key="analysis-finding-a06-f004" alt="저장소 루트에서 돌린 정적 검색 출력 288줄. 먼저 MongoFailureCategory 3~10번 클래스 자바독이 실리는데 서버 코드와 드라이버 오류 라벨은 릴리스마다 바뀌지만 이 범주는 안 바뀌며 메트릭과 대시보드에 나타나는 값이 이것이고, 그래서 알 수 없는 서버 코드가 런타임에 새 범주를 만드는 대신 UNCLASSIFIED 로 간다고 적는다. 63~72번에 OPERATION_REJECTED 와 SCHEMA_VERSION_UNSUPPORTED 와 UNCLASSIFIED 세 상수가 각자 주석과 함께 나오는데, 68번의 주석은 저장된 문서의 스키마 버전이 지원 범위 밖이라는 것이다. 이어서 MongoDataSchemaUnsupportedException 5~11번 자바독이 실리는데 도메인 역직렬화 전에 올라오는 것이 이 예외의 가치이고 새 릴리스가 쓴 문서나 은퇴한 버전이 남긴 문서를 현재 모양으로 조용히 밀어 넣으면 안 되며 버전은 정수라 메시지에 이름을 적어도 안전하다고 적는다. 22~39번 생성자가 세 정수를 요구하고 stored schema version 뒤에 문서 버전과 지원 범위를 이어 붙인 메시지를 만들며, 41~54번이 documentVersion 과 minimumSupported 와 currentVersion 세 공개 접근자다. 다음으로 new MongoDataSchemaUnsupportedException 을 부르는 main 자리가 둘 나오는데 MongoSchemaVersionPolicy 85번과 DefaultMongoFailureTranslator 111번이다. 그 아래 MongoSchemaVersionPolicy 82~87번이 실리는데 83~84번이 MongoFailureContext.rejected 로 context 를 만들고 85~86번이 version.value 와 range.minimumSupported().value 와 range.current().value 를 넘긴다. 이어서 MongoFailureContext 135~149번의 rejected 팩터리가 실리는데 140번이 MongoFailureCategory.OPERATION_REJECTED 를, 141번이 MongoExecutionOutcome.NOT_SENT 를 박는다. 다음으로 DefaultMongoFailureTranslator 88~118번이 실린다. 91번이 classification.category() 로 switch 를 열고 106번이 MongoDocumentTooLargeException 을 -1L 과 -1L 로, 110~111번이 MongoDataSchemaUnsupportedException 을 -1 과 -1 과 -1 로 만들며, 112~114번 주석이 벌크 부분 실패와 로컬 거절은 그 세부를 소유한 계층이 올리는 것이라 그 범주를 달고 번역까지 온 실패는 이 릴리스가 알아보지 못하는 것이라고 적고 115~116번이 그 셋을 MongoUnclassifiedFailureException 으로 보낸다. 이어서 SCHEMA_VERSION_UNSUPPORTED 가 저장소 전체에 나오는 줄이 2 개라고 나오고 그 둘이 MongoFailureCategory 68번의 선언과 DefaultMongoFailureTranslator 110번의 case 로 나열되며, 대조로 센 OPERATION_REJECTED 는 4 개다. 그 아래 DefaultMongoFailureClassifier 24~52번의 CATEGORY_BY_CODE 지도가 실리는데 서버 코드 11000 부터 31 까지 스물여섯 항목이 DUPLICATE_KEY 와 SCHEMA_VALIDATION 과 WRITE_CONFLICT 와 WRITE_CONCERN 과 READ_CONCERN 과 SERVER_SELECTION 과 CONNECTION 과 TIMEOUT 과 CURSOR 와 DOCUMENT_TOO_LARGE 와 SHARD_ROUTING 과 RESUME 과 ENCRYPTION 으로 가고 스키마 버전 항목이 없다. 이어서 같은 파일 86~120번이 실리는데 86~87번 주석이 라벨을 먼저 보는 이유가 서버 자신의 복구 가능성 진술이 어떤 코드 표보다 우선하기 때문이라고 적고, 88~89번과 91~92번이 커밋 미상과 일시적 트랜잭션 라벨을 각각 처리하며, 94~96번이 쓰기 없음 라벨을, 99번이 categoryOf 를, 101~109번이 아무것도 보내지 않은 단계에서 UNCLASSIFIED 를 SERVER_SELECTION 으로 바꾸는 것을, 111~112번이 커밋 단계의 미상 결과를 처리한다. 150~157번의 categoryOf 는 서버 코드가 없으면 재시도 가능 쓰기 라벨 여부로 CONNECTION 이나 UNCLASSIFIED 를 돌려주고 있으면 그 지도를 조회하며 없으면 UNCLASSIFIED 다. 그 아래 같은 정규식을 MongoFailureContextTest 에 걸면 1 개가 나온다는 대조가 있다. 다음으로 MongoFailureContext 151~172번의 schemaMismatch 팩터리가 실린다. 152~155번 자바독은 저장된 문서가 이 릴리스가 기대하는 스키마와 맞지 않는 경우이고 쓴 것이 없지만 읽기가 서버에 닿았으며 돌아온 것이 쓸 수 없는 값이라 결과가 NOT_SENT 가 아니라 NO_WRITE_PERFORMED 라고 적으며, 162번이 SCHEMA_VALIDATION 을 163번이 NO_WRITE_PERFORMED 를 박는다. 그 팩터리를 부르는 자리는 PolicyAwareMongoTypeMapper 112번과 185번과 192번이다. 이어서 new MongoSchemaVersionPolicy 를 부르는 main 줄이 0 개라고 나오고 그 타입이 main 에 나오는 자리가 MongoSchemaVersionPolicy 17번의 클래스 선언과 22번과 29번의 두 생성자 셋뿐이며, 대조로 센 시험 쪽 생성은 6 개다. DefaultMongoFailureTranslator 를 빈으로 만드는 main 줄은 2 개인데 MongoPlatformAutoConfiguration 93번과 DefaultMongoFailureTranslator 47번의 정적 팩터리다. 다음으로 MongoDocumentTooLargeException 26~36번이 실리는데 28번 자바독이 추정 직렬화 크기이며 내용이 아니라 크기라 로그에 남겨도 안전하다고만 적고, 33번은 초과된 상한이라고만 적는다. 마지막으로 MongoSchemaVersionPolicyTest 의 시험 여섯과 그 단언이 나오는데 21번과 31번과 45번이 isInstanceOf(MongoDataSchemaUnsupportedException.class) 이고 나머지는 resolveMissingVersion 과 writeVersion 과 requiresReadTimeConversion 과 음수 버전 거절을 본다. 그 시험이 category 나 세 버전 접근자를 단언하는 줄은 0 개다." caption="범주 열거형의 대시보드 자바독과 두 상수 · 전용 예외의 자바독과 세 접근자 · 프로덕션 생성 지점 둘 · 정책이 만드는 context 와 rejected 팩터리가 박는 값 · translator 의 switch 전문 · 그 범주가 저장소 전체에 두 줄뿐인 것과 분류기의 범주 지도 · 두 생성 지점의 조립 상태 · 같은 모양의 DocumentTooLarge · 정책 시험의 단언과 접근자 단언 0 — 288줄 · exit 0" zoom="true"
|
|
:::
|
|
|
|
`:3`\~`:9` 클래스 자바독이 이 열거형의 용도를 적는다. 릴리스마다 바뀌는 서버 코드와 드라이버 라벨 위에 얹는 고정된 값이고, 알 수 없는 서버 코드가 런타임에 새 범주를 만들어 메트릭 카디널리티를 터뜨리는 대신 `UNCLASSIFIED` 로 가는 이유가 그것이다.
|
|
|
|
`:68` 의 `SCHEMA_VERSION_UNSUPPORTED` 는 저장된 문서의 스키마 버전이 지원 범위 밖이라는 뜻이다. 바로 위 `:65` 의 `OPERATION_REJECTED` 는 플랫폼이 서버에 닿기 전에 로컬에서 거절했다는 뜻이다.
|
|
|
|
`MongoDataSchemaUnsupportedException:5`\~`:11` 은 이 예외가 도메인 역직렬화 전에 올라오는 것이 핵심이라고 적는다. 버전은 정수이고 데이터를 담지 않아서 메시지에 이름을 적어도 안전하다는 것도 함께 있다.
|
|
|
|
`:22`\~`:39` 의 생성자가 그 셋을 요구하고 메시지를 조립한다. `:42`·`:47`·`:52` 가 `documentVersion()` 과 `minimumSupported()` 와 `currentVersion()` 이다. 분기할 범주와 진단할 값이 둘 다 준비돼 있다.
|
|
|
|
## 생성 지점 둘
|
|
|
|
`new MongoDataSchemaUnsupportedException` 을 부르는 main 자리는 `MongoSchemaVersionPolicy:85` 와 `DefaultMongoFailureTranslator:111` 둘이다.
|
|
|
|
## MongoSchemaVersionPolicy 가 넘기는 context 의 범주
|
|
|
|
`MongoSchemaVersionPolicy:85`\~`:86` 이 `version.value()` 와 `range.minimumSupported().value()` 와 `range.current().value()` 를 넘긴다. 진짜 값이다.
|
|
|
|
그런데 `:83`\~`:84` 가 그 예외에 넣을 context 를 `MongoFailureContext.rejected(new MongoOperationName("schema.version-check"))` 로 만든다.
|
|
|
|
`MongoFailureContext:135`\~`:148` 이 그 팩터리다. `:140` 이 범주를 `OPERATION_REJECTED` 로, `:141` 이 결과를 `NOT_SENT` 로 박는다. 인자로 받는 것은 연산 이름 하나뿐이라 다른 범주를 넣을 자리가 없다.
|
|
|
|
## DefaultMongoFailureTranslator\:111 이 넣는 -1, -1, -1
|
|
|
|
`DefaultMongoFailureTranslator:91` 이 `classification.category()` 로 `switch` 를 연다. `:110`\~`:111` 이 그 범주를 받으면 `MongoDataSchemaUnsupportedException` 을 `-1, -1, -1` 로 만든다.
|
|
|
|
여기서는 버전을 알 수 없다. 드라이버가 보고한 실패에서 문서의 스키마 버전을 읽을 방법이 없기 때문이다.
|
|
|
|
## 그 case 에 들어오는 값이 없다
|
|
|
|
`SCHEMA_VERSION_UNSUPPORTED` 가 저장소 전체에 나오는 줄은 둘이다. `MongoFailureCategory:68` 의 선언과 `DefaultMongoFailureTranslator:110` 의 `case` 다. `OPERATION_REJECTED` 로 같은 검색을 걸면 넷이 나온다. 2 는 pathspec 이 아무것도 훑지 못해 나온 값이 아니다.
|
|
|
|
분류기가 범주를 정하는 자리는 하나가 아니다. `:88`\~`:89` 와 `:91`\~`:92` 가 드라이버 라벨을 먼저 보고 커밋 미상이나 일시적 트랜잭션으로 보내고, `:94`\~`:96` 이 쓰기 없음 라벨을 처리하며, `:99` 가 `categoryOf` 를 부르고, `:106`\~`:109` 가 아무것도 보내지 않은 단계에서 `UNCLASSIFIED` 를 `SERVER_SELECTION` 으로 바꾸고, `:112` 가 커밋 단계의 미상 결과를 처리한다.
|
|
|
|
마지막이 `:150`\~`:157` 의 `categoryOf` 다. 서버 코드가 없으면 재시도 가능 쓰기 라벨 여부로 `CONNECTION` 이나 `UNCLASSIFIED` 를 주고, 있으면 `CATEGORY_BY_CODE` 를 조회한다. 그 지도 `:27`\~`:52` 의 스물여섯 항목이 열세 범주로 나뉘는데 스키마 버전이 없다.
|
|
|
|
어느 자리에서도 `SCHEMA_VERSION_UNSUPPORTED` 가 나오지 않는다. 그 이름이 저장소 전체에 두 줄뿐이라는 계수가 그것을 한 번에 말한다.
|
|
|
|
그래서 `classification.category()` 가 `SCHEMA_VERSION_UNSUPPORTED` 인 경우가 생기지 않고, `-1, -1, -1` 예외는 만들어지지 않는다.
|
|
|
|
## 두 생성 지점의 조립 상태가 반대다
|
|
|
|
`DefaultMongoFailureTranslator` 는 빈이다. `MongoPlatformAutoConfiguration:93` 이 분류기를 넣어 만들고, `DefaultMongoFailureTranslator:47` 에 기본 분류기를 쓰는 정적 팩터리도 있다. 조립돼 있는데 문제의 분기만 죽었다.
|
|
|
|
`MongoSchemaVersionPolicy` 는 반대다. `new MongoSchemaVersionPolicy` 를 부르는 main 줄이 0 이고, 그 이름이 main 에 나오는 자리는 `:17` 의 클래스 선언과 `:22`·`:29` 의 두 생성자뿐이다. 같은 검색을 시험에 걸면 여섯이 나온다.
|
|
|
|
그래서 이 리비전에서는 세 버전을 아는 예외가 아예 던져지지 않는다. 대시보드의 `SCHEMA_VERSION_UNSUPPORTED` 칸이 비는 것은 맞지만, `OPERATION_REJECTED` 칸으로 새는 것도 아직 없다.
|
|
|
|
이 정책은 채택자가 쓰라고 공개된 타입이다. 배선하는 순간 스키마 버전 거절이 로컬 가드레일 거절과 같은 칸에 들어가고, 전용 칸은 계속 비어 있다.
|
|
|
|
`MongoSchemaVersionPolicyTest` 의 `:21`·`:31`·`:45` 는 `isInstanceOf` 로 예외 타입만 확인한다. 나머지 시험은 `resolveMissingVersion` 과 `writeVersion` 과 `requiresReadTimeConversion` 과 음수 버전 거절을 본다. `category()` 나 세 접근자가 나오는 줄이 하나도 없다.
|
|
|
|
같은 정규식을 `MongoFailureContextTest` 에 걸면 1 이 나온다. 0 은 그 정규식이 아무것도 못 잡아서 나온 값이 아니다.
|
|
|
|
## 살아 있는 스키마 실패는 세 번째 범주로 간다
|
|
|
|
`MongoFailureContext:151`\~`:171` 에 `schemaMismatch` 팩터리가 있다. `:162` 가 `SCHEMA_VALIDATION` 을, `:163` 이 `NO_WRITE_PERFORMED` 를 박는다. `:154`\~`:155` 자바독이 그 결과를 고른 이유를 적는다 — 쓴 것이 없지만 읽기는 서버에 닿았고 돌아온 것이 쓸 수 없는 값이라는 것이다.
|
|
|
|
부르는 자리는 `PolicyAwareMongoTypeMapper:112`·`:185`·`:192` 셋이다. 타입 매퍼가 문서를 도메인 타입으로 옮기다 실패할 때 도는 경로다.
|
|
|
|
그래서 이 모듈의 스키마 관련 실패는 세 범주로 갈린다. 타입 매퍼가 쓰는 `SCHEMA_VALIDATION`, 조립되지 않은 정책이 쓰는 `OPERATION_REJECTED`, 그리고 아무도 만들지 않는 `SCHEMA_VERSION_UNSUPPORTED` 다.
|
|
|
|
## -1 을 넣는 다른 예외 하나
|
|
|
|
`DefaultMongoFailureTranslator:106` 이 `MongoDocumentTooLargeException` 을 `-1L, -1L` 로 만든다.
|
|
|
|
`MongoDocumentTooLargeException:28` 은 그 값을 추정 직렬화 크기라고, `:33` 은 초과된 상한이라고 적는다. 값이 없을 수 있다는 말은 없다.
|
|
|
|
이쪽은 도달 가능하다. `CATEGORY_BY_CODE:46`\~`:47` 이 서버 코드 10334 와 17420 을 `DOCUMENT_TOO_LARGE` 로 보낸다. 드라이버가 보고한 실패에서 두 수를 알 수 없는 것은 어쩔 수 없지만, 접근자 계약에 그 사실이 없다.
|
|
|
|
## 원문과 갈리는 자리
|
|
|
|
원문은 생성 지점이 둘이고 각각 반쪽만 맞다고 적으면서, 전용 범주 칸이 세 버전이 `-1` 인 실패만 받는다고 적는다.
|
|
|
|
확인 결과는 다르다. 분류기가 그 범주를 만들지 않으므로 `-1` 예외조차 생기지 않고, `DefaultMongoFailureTranslator:110`\~`:111` 에는 값이 들어오지 않는다. 원문이 제안한 수정 — 정책이 전용 범주를 가진 context 를 만들면 translator 쪽 `-1` 경로를 정리할 수 있다 — 은 그대로 맞고, 정리 대상이 이미 실행되지 않는 `case` 라는 점만 다르다.
|
|
|
|
## 확인하지 못한 것
|
|
|
|
다른 분류기 구현이 조립될 수 있는지는 조립 경로로 따지지 않았다. 도달 불가라는 판정은 이름 계수 하나에 기대고 있다.
|
|
|
|
이 범주 이름을 소비하는 대시보드나 메트릭 설정은 저장소 밖에 있어 보지 않았다.
|
|
|
|
`MongoSchemaVersionPolicy` 가 던진 예외를 잡는 호출자가 세 접근자를 읽어 진단에 쓰는지 추적하지 않았다.
|
|
|
|
<!-- body:end -->
|