Files
document-haness/docs/clean-architecture-backend-template/final/evidence/raw/a-startup-probe-that-never-runs.txt
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

71 lines
3.8 KiB
Plaintext

# 탐침이 자기를 소개하는 문단
/**
* Asks the server what it is, once, at startup.
*
* <p>Configuration says what the deployment intends; only the server says what is true. The version
* a managed Redis advertises does not imply the modules are present, and a replicated deployment's
* write durability is a server setting no client can compensate for. Both are cheap to ask and
* expensive to discover later — a missing capability found at the first request is an outage, found
* here it is a failed deploy.
# 그것이 확인하는 넷
RedisCapabilities capabilities =
probe.probe(
serverFacts.version(),
settings.getMode(),
settings.getDatabase(),
commandPresence(serverFacts.commands()),
requiredCapabilities);
probe.requireWriteDurability(
settings.getMode(),
serverFacts.minReplicasToWrite(),
serverFacts.minReplicasMaxLagSeconds(),
settings.isAcknowledgedWriteLossAccepted());
return capabilities;
}
# 넷째의 javadoc — 실측과 결론
* Refuses to start against a replicated deployment that cannot keep the writes it acknowledges.
*
* <p>This is the one server-side setting the SDK cannot compensate for. When a primary is
* superseded by a promotion it does not find out immediately, and until it does it keeps
* answering {@code +OK} to writes that are discarded when it resyncs from the new primary. The
* Sentinel lane measured eleven seconds and 2,086 acknowledged-then-discarded writes, with
* exactly one command failing. No client can see it: the server answered, so the driver, this
* SDK, and the caller all record a success. There is no metric to add, no failure to retry, and
* no certainty value that describes it.
*
* <p>{@code min-replicas-to-write} with a bounded {@code min-replicas-max-lag} is what turns that
* into a {@code NOREPLICAS} refusal the caller can act on — the same promotion then lost one
* write instead of 2,086. So a replicated deployment without it is a startup failure rather than
* a warning, on the same principle as every other guardrail here: a setting that makes a
* guarantee meaningless stops the context instead of degrading quietly.
# 그리고 검사가 두 겹인 이유
* <p>Both halves of the guarantee are checked. A replica count on its own decides only how many
* replicas must be <em>connected</em>; how far behind they may be is {@code
* min-replicas-max-lag}, and Redis treats {@code 0} there as "no lag requirement". A deployment
* with {@code min-replicas-to-write 2} and {@code min-replicas-max-lag 0} therefore accepts a
* write once two arbitrarily stale replicas are attached, which is the same lost-write exposure
* the count was supposed to remove. Checking the count alone let that configuration pass while
* the failure message told the operator to set the lag bound.
# 그 실패는 일어나지 않는다
두 탐침 밖에서 그것들을 언급하는 main 코드: 1
RedisSdkSettings.java:888: * signal exists for it; see {@link RedisCapabilityProbe#requireWriteDurability}.
confirm( 을 부르는 main 코드: 0
# 자동설정이 만드는 빈
85 public RedisSdkSettings redisSdkSettings() {
102 public RedisSdkSettingsValidation redisSdkSettingsValidation(
157 public RedisResolvedCredentials redisResolvedCredentials(
227 public RedisRuntimeClient redisRuntimeClient(
274 public RedisRuntimeOwner redisRuntimeOwner(RedisRuntimeClient client, RedisSdkSettings settings) {
298 public HealthIndicator redisOptional(RedisRuntimeOwner owner, RedisSdkSettings settings) {
326 public HealthIndicator redisRequired(RedisRuntimeOwner owner, RedisSdkSettings settings) {
그중 탐침: 0
# 로직을 고정하는 테스트 케이스 수
RedisCapabilityProbeTest: 11
RedisStartupProbeTest: 7