Files
document-haness/docs/clean-architecture-backend-template/tech-log-studio/operator-approval-and-destructive-operations/case/case-blocking-means-startup-fails-and-nothing-runs-it.md
T
DongHyeonkaandClaude Opus 5 b2963105a8 docs(keycloak-session-store): import the session-storage lab as a new project
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>
2026-09-04 22:51:59 +09:00

6.1 KiB

kind, slug, title, topic, project, status, sourceRevision, rootTreeNode, evidenceCapturedOn, assets, evidence, source
kind slug title topic project status sourceRevision rootTreeNode evidenceCapturedOn assets evidence source
CASE blocking-means-startup-fails-and-nothing-runs-it BLOCKING 이면 기동이 실패한다는 보장이 어떤 배선에서도 실행되지 않는다 operator-approval-and-destructive-operations clean-architecture-backend-template 게시 전 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916 case:blocking-means-startup-fails-and-nothing-runs-it 2026-09-01
key file
blocking-means-startup-fails-and-nothing-runs-it ../../../final/evidence/rendered/blocking-means-startup-fails-and-nothing-runs-it.svg
../../../final/evidence/raw/blocking-means-startup-fails-and-nothing-runs-it.txt
원본 분석 절은 analysis/messaging/messaging-admin-api.md §17 P2 이다.

BLOCKING 이면 기동이 실패한다는 보장이 어떤 배선에서도 실행되지 않는다

토폴로지 검증에서 차단 심각도는 기동을 실패시킨다고 두 javadoc 이 적는다. 그 판정을 부르는 production 코드가 없고, 그것을 부를 수 있는 유일한 진입점도 호출자가 없으며, 서비스 빈을 스타터가 만들지 않는다.

관계

  • 승인·검증·실행의 분리와 그것을 타입으로 표현하기 이 사례가 속한 표면이다.
  • 검증기는 발행이 아니라 주입이 강제다 이 사례가 어기는 규칙이다.
  • 시작 검증기가 도는지는 그 능력에 자동설정 루트가 있는지와 일치한다 같은 계열의 판정 규칙이다.
  • 시작 검증기 13개 규칙이 유일한 조립 지점에서 호출되지 않는다 같은 형태가 gRPC 쪽에서 나타난 사례다.

문제

목적지 프로파일은 보장을 선언한다. 내구성이 필요하다거나, 순서가 필요하다거나, 특정 복제 수준이 필요하다는 선언이다.

브로커의 실제 토폴로지가 그 보장을 줄 수 없으면 그것은 기동 시점에 잡아야 한다. 런타임에 발견하면 이미 메시지를 받은 뒤다.

결론

타입은 그 상황을 정확히 표현하고, 표현한 것을 아무도 읽지 않는다.

심각도 열거형의 차단 값 javadoc 이 적는다.

The destination cannot deliver a declared guarantee; startup must fail.

검증 보고서의 수용 가능성 요구 메서드 javadoc 이 적는다.

Fails startup when any blocking issue was found.

그 메서드의 production 호출부가 0이다. 그것을 부를 수 있는 유일한 진입점인 토폴로지 검증 메서드도 호출부가 0이고, 그 메서드를 가진 서비스 빈을 스타터가 만들지 않는다.

결과: 복제 계수가 1인 목적지에 내구성을 선언해도 컨텍스트는 정상 기동한다.

고치는 방법이 같은 리프에 이미 있다. 내구성 검증기가 초기화 콜백으로 저널 내구성을 기동 시점에 검사하고 실패시킨다. 같은 모양의 빈 하나면 된다. 다만 브로커 검사기가 없으면 검증할 수 없으므로 그 조건부는 유지해야 한다.

이 항목이 무거운 이유는 리프가 출하 애플리케이션 소속이고, 보장이 문서와 타입과 테스트 세 겹으로 존재하는데 배선만 없다는 점이다. 읽는 사람은 보장이 있다고 믿을 근거를 세 개 갖는다.

그리고 토폴로지 검증 스택이 이 가족에 두 벌 있다. 파티션 스케일업에 대해 한쪽은 권고로 두어 기동을 허용하고 다른 쪽은 차이로 보아 거부한다. 둘 다 호출자가 0이라 지금은 충돌하지 않지만, 배선하는 순간 어느 스택을 고르느냐가 스케일업한 배포의 기동 여부를 가른다.

검증 환경

OpenJDK : 21.0.12 Gradle : 9.0.0 확인 방식 : 두 메서드의 호출자 전수 검색과 스타터의 빈 목록 확인 소스 수정 : x

재현 조건

원문은 final/evidence/raw/302-admin-api-topology-guarantee-unwired.txt (EVD-302) 에 있다.

  1. 차단 심각도와 수용 가능성 요구 메서드의 javadoc 을 읽는다.
  2. 그 메서드의 호출자를 저장소에서 검색한다.
  3. 그것을 부를 수 있는 진입점의 호출자를 검색한다.
  4. 스타터가 그 서비스 빈을 만드는지 확인한다.
  5. 같은 리프의 내구성 검증기가 어떻게 배선되어 있는지 확인한다.

본문

BLOCKING 의 javadoc 이 "The destination cannot deliver a declared guarantee; startup must fail" 이라고 적고, requireAcceptable() 의 javadoc 이 "Fails startup when any blocking issue was found" 라고 적는다.

MessagingAdminDurabilityValidator 참조 위치

:::evidence key="blocking-means-startup-fails-and-nothing-runs-it" alt="코드베이스에서 MessagingAdminDurabilityValidator 를 검색한 출력 3줄. 이 기록이 세는 참조가 그 출력에 그대로 보인다." caption="MessagingAdminDurabilityValidator 코드베이스 검색 — 3줄 · exit 0" zoom="true" :::

세 겹으로 호출자가 없다

그 메서드의 production 호출부가 0 이고, 그것을 부를 수 있는 유일한 진입점도 호출부가 0 이며, 그 서비스 빈을 스타터가 만들지 않는다. 결과적으로 복제 계수 1인 목적지에 내구성을 선언해도 컨텍스트는 정상 기동한다. 타입은 그 상황을 정확히 표현할 수 있고 표현한 것을 아무도 읽지 않는다.

고치는 방법이 같은 리프에 이미 있다

MessagingAdminDurabilityValidatorInitializingBean 으로 저널 내구성을 기동 시점에 검사하고 실패시킨다. 같은 모양의 빈 하나면 된다.

이 항목이 무거운 이유

이 리프가 app-bootstrap 소속이고 보장이 문서·타입·테스트 세 겹으로 존재하는데 배선만 없다 — 읽는 사람은 보장이 있다고 믿을 근거를 세 개 갖는다. 그리고 토폴로지 검증 스택이 이 리프에 두 벌 있고 파티션 스케일업에 대한 판정이 서로 반대라, 배선하는 순간 어느 스택을 고르느냐가 스케일업한 배포의 기동 여부를 가른다. P2.

확인하지 못한 것

컨텍스트를 세워 기동 성공을 관측하지 않았다. 호출부 부재로 판정했다.