Files
document-haness/docs/clean-architecture-backend-template/final/evidence/rendered/analysis-finding-a06-f019.svg
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

283 lines
59 KiB
XML

<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="5804" viewBox="0 0 1200 5804" role="img">
<title>terminal evidence</title>
<desc>Terminal-style rendering generated from retained command output. Sensitive-looking values are redacted in the visual asset.</desc>
<rect x="1" y="1" width="1198" height="5802" rx="14" fill="#0d1117" stroke="#30363d"/>
<rect x="1" y="1" width="1198" height="44" rx="14" fill="#161b22"/>
<rect x="1" y="30" width="1198" height="14" fill="#161b22"/>
<circle cx="24" cy="22" r="6" fill="#ff5f57"/>
<circle cx="44" cy="22" r="6" fill="#febc2e"/>
<circle cx="64" cy="22" r="6" fill="#28c840"/>
<text x="92" y="27" fill="#8b949e" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace">terminal evidence</text>
<text x="24" y="68" fill="#c9d1d9" font-size="15" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">$ #!/bin/bash
set -euo pipefail
cd /shared/codebase/clean-architecture-backend-template
. /tmp/lib.sh
R=src/adapter/outb</tspan><tspan x="24" dy="22">ound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/changestream
P=$R/recovery/MongoChangeStreamR</tspan><tspan x="24" dy="22">ecoveryPolicy.java
I=$R/recovery/MongoInvalidateRecovery.java
X=$R/recovery/MongoChangeHistoryLostException.java
S=$R/Mo</tspan><tspan x="24" dy="22">ngoChangeStreamState.java
C=$(git ls-files -- &#x27;**/ReactiveMongoChangeStreamConsumer.java&#x27;)
L=$(git ls-files -- &#x27;**/Chang</tspan><tspan x="24" dy="22">eStreamConsumerLifecycleTest.java&#x27;)
for f in &quot;$P&quot; &quot;$I&quot; &quot;$X&quot; &quot;$S&quot; &quot;$C&quot; &quot;$L&quot;; do test -f &quot;$f&quot;; done
echo &quot;# 복구 패키지가</tspan><tspan x="24" dy="22"> 선언한 것&quot;
git ls-files -- &quot;$R/recovery/*.java&quot; | sed &#x27;s#.*/# #&#x27;
at &quot;$P&quot; 7 66 MongoChangeStreamRecoveryPolicy.java
ec</tspan><tspan x="24" dy="22">ho
echo &quot;# 각 진입점의 프로덕션 호출 계수&quot;
for n in &#x27;onFailure&#x27; &#x27;onHistoryLost&#x27; &#x27;onResumableFailure&#x27; &#x27;onInvalidate&#x27; &#x27;req</tspan><tspan x="24" dy="22">uireCorrectResumeOption&#x27; &#x27;checkpointFor&#x27; &#x27;autoResumable&#x27;; do
printf &#x27; %-28s main %s · test %s\n&#x27; &quot;$n&quot; \
&quot;$(lines</tspan><tspan x="24" dy="22"> &quot;\\.$n\\(&quot; &#x27;src/**/src/main/**/*.java&#x27;)&quot; \
&quot;$(lines &quot;\\.$n\\(&quot; &#x27;src/**/src/*[Tt]est*/**/*.java&#x27;)&quot;
done
printf &#x27; %-</tspan><tspan x="24" dy="22">28s main %s · test %s\n&#x27; &#x27;new MongoChangeHistoryLost..&#x27; \
&quot;$(lines &#x27;new MongoChangeHistoryLostException&#x27; &#x27;src/**/src/</tspan><tspan x="24" dy="22">main/**/*.java&#x27;)&quot; \
&quot;$(lines &#x27;new MongoChangeHistoryLostException&#x27; &#x27;src/**/src/*[Tt]est*/**/*.java&#x27;)&quot;
printf &#x27; [대조]</tspan><tspan x="24" dy="22"> onInvalidate 라는 이름이 나오는 줄 전부 : %s 개\n&#x27; &quot;$(lines &#x27;onInvalidate&#x27; &#x27;src/**/*.java&#x27;)&quot;
printf &#x27; 그 예외 이름이 </tspan><tspan x="24" dy="22">자바 소스에 나오는 줄 : %s 개\n&#x27; &quot;$(lines &#x27;MongoChangeHistoryLostException&#x27; &#x27;src/**/*.java&#x27;)&quot;
hits &#x27;MongoChangeHistoryLo</tspan><tspan x="24" dy="22">stException&#x27; &#x27;src/**/*.java&#x27; \
| sed -E &#x27;s#^src/(.*)/src/([a-zA-Z]+)/java/.*/([A-Za-z0-9_$]+\.java):([0-9]+): *# \2</tspan><tspan x="24" dy="22"> · \3:\4 #&#x27;
echo &quot; 같은 이름을 문서가 쓰는 자리 :&quot;
{ git grep -n &#x27;MongoChangeHistoryLostException&#x27; -- &#x27;docs/mongodb&#x27; </tspan><tspan x="24" dy="22">&#x27;docs/architecture&#x27; || true; } \
| sed -E &#x27;s#^(docs/[^:]+):([0-9]+): *# \1:\2 #&#x27;
echo
echo &quot;# 쓰이지 않는 예외가 </tspan><tspan x="24" dy="22">자기 존재 이유로 적은 것&quot;
at &quot;$X&quot; 8 29 MongoChangeHistoryLostException.java
echo
echo &quot;# 실제로 history lost 를 다루는 </tspan><tspan x="24" dy="22">자리&quot;
at &quot;$P&quot; 50 61 MongoChangeStreamRecoveryPolicy.java
echo &quot; 소비자가 그 결정을 받는 자리 :&quot;
hits &#x27;recovery\.on[A-Za</tspan><tspan x="24" dy="22">-z]+\(|invalidates\.&#x27; &quot;$C&quot; \
| sed -E &#x27;s#^.*/([A-Za-z0-9_]+\.java):([0-9]+): *# \1:\2 #&#x27;
echo &quot; history lost 일 </tspan><tspan x="24" dy="22">때 호출자가 실제로 받는 것 :&quot;
at &quot;$L&quot; 108 124 ChangeStreamConsumerLifecycleTest.java
echo
echo &quot;# 자기 자신과 견주는 검</tspan><tspan x="24" dy="22">&quot;
at &quot;$I&quot; 24 45 MongoInvalidateRecovery.java
echo &quot; 그 메서드를 부르는 자리 전부 :&quot;
hits &#x27;requireCorrectResumeOption&#x27;</tspan><tspan x="24" dy="22"> &#x27;src/**/*.java&#x27; \
| sed -E &#x27;s#^src/(.*)/src/([a-zA-Z]+)/java/.*/([A-Za-z0-9_$]+\.java):([0-9]+): *# \2 · \3:\4 #</tspan><tspan x="24" dy="22">&#x27;
echo
echo &quot;# 상태 열거형이 그 구분을 어떻게 적는가&quot;
at &quot;$S&quot; 1 35 MongoChangeStreamState.java
</tspan></text>
<text x="24" y="574" fill="#8b949e" font-size="13" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">cwd: /shared/codebase/clean-architecture-backend-template</tspan></text>
<text x="24" y="596" fill="#8b949e" font-size="13" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">time: 2026-09-04T08:26:11+00:00 · exit 0</tspan></text>
<line x1="24" y1="610" x2="1176" y2="610" stroke="#30363d"/>
<text x="24" y="650" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 복구 패키지가 선언한 것</tspan></text>
<text x="24" y="672" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java</tspan></text>
<text x="24" y="694" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryDecision.java</tspan></text>
<text x="24" y="716" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java</tspan></text>
<text x="24" y="738" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java</tspan></text>
<text x="24" y="760" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:7 /**</tspan></text>
<text x="24" y="782" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:8 * Decides how a change stream reacts to each kind of failure (design §20.3).</tspan></text>
<text x="24" y="804" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:9 *</tspan></text>
<text x="24" y="826" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:10 * &lt;p&gt;Three classes with three different answers. A resumable network or election fail</tspan><tspan x="24" dy="22">ure resumes</tspan></text>
<text x="24" y="870" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:11 * automatically, because the stored token is still valid. An invalidate — a dropped </tspan><tspan x="24" dy="22">or renamed</tspan></text>
<text x="24" y="914" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:12 * collection — needs {@code startAfter} rather than {@code resumeAfter}, which the d</tspan><tspan x="24" dy="22">river will not</tspan></text>
<text x="24" y="958" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:13 * do implicitly. A lost history needs a human.</tspan></text>
<text x="24" y="980" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:14 */</tspan></text>
<text x="24" y="1002" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:15 public final class MongoChangeStreamRecoveryPolicy {</tspan></text>
<text x="24" y="1024" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:16 </tspan></text>
<text x="24" y="1046" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:17 /** Runbook for a subscription whose oplog history was lost. */</tspan></text>
<text x="24" y="1068" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:18 public static final String HISTORY_LOST_RUNBOOK = &quot;docs/mongodb/runbooks/history-los</tspan><tspan x="24" dy="22">t.md&quot;;</tspan></text>
<text x="24" y="1112" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:19 </tspan></text>
<text x="24" y="1134" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:20 /** Runbook for a subscription that failed for a non-resumable reason. */</tspan></text>
<text x="24" y="1156" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:21 public static final String FAILURE_RUNBOOK = &quot;docs/mongodb/runbooks/failover.md&quot;;</tspan></text>
<text x="24" y="1178" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:22 </tspan></text>
<text x="24" y="1200" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:23 /**</tspan></text>
<text x="24" y="1222" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:24 * The decision for a lost oplog history.</tspan></text>
<text x="24" y="1244" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:25 *</tspan></text>
<text x="24" y="1266" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:26 * &lt;p&gt;Never auto-resumes. The alternative — restarting from the current time — pro</tspan><tspan x="24" dy="22">duces a</tspan></text>
<text x="24" y="1310" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:27 * projection that is missing an unknown range of changes and reports itself as heal</tspan><tspan x="24" dy="22">thy.</tspan></text>
<text x="24" y="1354" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:28 */</tspan></text>
<text x="24" y="1376" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:29 public MongoChangeStreamRecoveryDecision onHistoryLost(String subscriptionProfile) {</tspan></text>
<text x="24" y="1398" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:30 Objects.requireNonNull(subscriptionProfile, &quot;subscriptionProfile&quot;);</tspan></text>
<text x="24" y="1420" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:31 return MongoChangeStreamRecoveryDecision.halt(</tspan></text>
<text x="24" y="1442" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:32 MongoChangeStreamState.HISTORY_LOST, HISTORY_LOST_RUNBOOK);</tspan></text>
<text x="24" y="1464" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:33 }</tspan></text>
<text x="24" y="1486" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:34 </tspan></text>
<text x="24" y="1508" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:35 /** The decision for a resumable failure such as a primary failover. */</tspan></text>
<text x="24" y="1530" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:36 public MongoChangeStreamRecoveryDecision onResumableFailure() {</tspan></text>
<text x="24" y="1552" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:37 return MongoChangeStreamRecoveryDecision.resume();</tspan></text>
<text x="24" y="1574" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:38 }</tspan></text>
<text x="24" y="1596" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:39 </tspan></text>
<text x="24" y="1618" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:40 /**</tspan></text>
<text x="24" y="1640" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:41 * The decision for an invalidate event.</tspan></text>
<text x="24" y="1662" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:42 *</tspan></text>
<text x="24" y="1684" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:43 * &lt;p&gt;Resumes, but the checkpoint the caller stores must be a {@code startAfter} pos</tspan><tspan x="24" dy="22">ition — the</tspan></text>
<text x="24" y="1728" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:44 * subscription is otherwise unresumable, because {@code resumeAfter} rejects an inv</tspan><tspan x="24" dy="22">alidate token.</tspan></text>
<text x="24" y="1772" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:45 */</tspan></text>
<text x="24" y="1794" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:46 public MongoChangeStreamRecoveryDecision onInvalidate() {</tspan></text>
<text x="24" y="1816" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:47 return MongoChangeStreamRecoveryDecision.resume();</tspan></text>
<text x="24" y="1838" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:48 }</tspan></text>
<text x="24" y="1860" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:49 </tspan></text>
<text x="24" y="1882" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:50 /** The decision for a failure the platform cannot classify as resumable. */</tspan></text>
<text x="24" y="1904" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:51 public MongoChangeStreamRecoveryDecision onFailure(MongoDriverFailureView failure) {</tspan></text>
<text x="24" y="1926" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:52 Objects.requireNonNull(failure, &quot;failure&quot;);</tspan></text>
<text x="24" y="1948" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:53 if (failure.hasServerCode() &amp;&amp; isHistoryLost(failure.serverCode())) {</tspan></text>
<text x="24" y="1970" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:54 return MongoChangeStreamRecoveryDecision.halt(</tspan></text>
<text x="24" y="1992" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:55 MongoChangeStreamState.HISTORY_LOST, HISTORY_LOST_RUNBOOK);</tspan></text>
<text x="24" y="2014" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:56 }</tspan></text>
<text x="24" y="2036" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:57 if (failure.hasLabel(&quot;ResumableChangeStreamError&quot;)) {</tspan></text>
<text x="24" y="2058" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:58 return MongoChangeStreamRecoveryDecision.resume();</tspan></text>
<text x="24" y="2080" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:59 }</tspan></text>
<text x="24" y="2102" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:60 return MongoChangeStreamRecoveryDecision.halt(MongoChangeStreamState.FAILED, FAILU</tspan><tspan x="24" dy="22">RE_RUNBOOK);</tspan></text>
<text x="24" y="2146" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:61 }</tspan></text>
<text x="24" y="2168" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:62 </tspan></text>
<text x="24" y="2190" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:63 /** {@code ChangeStreamHistoryLost} and {@code ChangeStreamFatalError}. */</tspan></text>
<text x="24" y="2212" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:64 private static boolean isHistoryLost(int serverCode) {</tspan></text>
<text x="24" y="2234" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:65 return serverCode == 286 || serverCode == 280;</tspan></text>
<text x="24" y="2256" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:66 }</tspan></text>
<text x="24" y="2278" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"></tspan></text>
<text x="24" y="2300" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 각 진입점의 프로덕션 호출 계수</tspan></text>
<text x="24" y="2322" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> onFailure main 1 · test 3</tspan></text>
<text x="24" y="2344" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> onHistoryLost main 0 · test 1</tspan></text>
<text x="24" y="2366" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> onResumableFailure main 0 · test 1</tspan></text>
<text x="24" y="2388" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> onInvalidate main 0 · test 0</tspan></text>
<text x="24" y="2410" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> requireCorrectResumeOption main 1 · test 1</tspan></text>
<text x="24" y="2432" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> checkpointFor main 0 · test 1</tspan></text>
<text x="24" y="2454" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> autoResumable main 0 · test 3</tspan></text>
<text x="24" y="2476" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> new MongoChangeHistoryLost.. main 0 · test 0</tspan></text>
<text x="24" y="2498" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> [대조] onInvalidate 라는 이름이 나오는 줄 전부 : 2 개</tspan></text>
<text x="24" y="2520" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> 그 예외 이름이 자바 소스에 나오는 줄 : 2 개</tspan></text>
<text x="24" y="2542" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> main · MongoChangeHistoryLostException.java:16 public final class MongoChangeHistoryLostException extends MongoPersistence</tspan><tspan x="24" dy="22">Exception {</tspan></text>
<text x="24" y="2586" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> main · MongoChangeHistoryLostException.java:22 public MongoChangeHistoryLostException(</tspan></text>
<text x="24" y="2608" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> 같은 이름을 문서가 쓰는 자리 :</tspan></text>
<text x="24" y="2630" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> docs/architecture/mongo-api-surface.txt:168 dev.caskeleton.adapter.outbound.mongo.changestream.recovery.MongoChangeHistoryL</tspan><tspan x="24" dy="22">ostException</tspan></text>
<text x="24" y="2674" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> docs/mongodb/change-stream-guide.md:71 | Token no longer in the oplog | `halt(HISTORY_LOST, &quot;history-lost&quot;)` → `MongoChang</tspan><tspan x="24" dy="22">eHistoryLostException` |</tspan></text>
<text x="24" y="2718" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> docs/mongodb/change-stream-guide.md:75 `MongoChangeHistoryLostException` is raised when the resume token predates the oldes</tspan><tspan x="24" dy="22">t oplog entry.</tspan></text>
<text x="24" y="2762" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> docs/mongodb/runbooks/history-lost.md:23 - `MongoChangeHistoryLostException`.</tspan></text>
<text x="24" y="2784" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"></tspan></text>
<text x="24" y="2806" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 쓰이지 않는 예외가 자기 존재 이유로 적은 것</tspan></text>
<text x="24" y="2828" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java:8 /**</tspan></text>
<text x="24" y="2850" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java:9 * The oplog no longer contains the stored resume position (design §20.3).</tspan></text>
<text x="24" y="2872" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java:10 *</tspan></text>
<text x="24" y="2894" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java:11 * &lt;p&gt;A dedicated type because the recovery is a business decision, not a technical on</tspan><tspan x="24" dy="22">e. The</tspan></text>
<text x="24" y="2938" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java:12 * platform could resume from &quot;now&quot; — the driver makes it easy — and the projection </tspan><tspan x="24" dy="22">would silently</tspan></text>
<text x="24" y="2982" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java:13 * miss every change that fell off the oplog. The only honest options are rebuilding t</tspan><tspan x="24" dy="22">he projection</tspan></text>
<text x="24" y="3026" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java:14 * or reconciling it against the source, and both need someone to choose.</tspan></text>
<text x="24" y="3048" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java:15 */</tspan></text>
<text x="24" y="3070" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java:16 public final class MongoChangeHistoryLostException extends MongoPersistenceException {</tspan></text>
<text x="24" y="3092" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java:17 </tspan></text>
<text x="24" y="3114" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java:18 @Serial private static final long serialVersionUID = 1L;</tspan></text>
<text x="24" y="3136" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java:19 </tspan></text>
<text x="24" y="3158" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java:20 private final String subscriptionProfile;</tspan></text>
<text x="24" y="3180" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java:21 </tspan></text>
<text x="24" y="3202" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java:22 public MongoChangeHistoryLostException(</tspan></text>
<text x="24" y="3224" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java:23 MongoFailureContext failureContext, String subscriptionProfile) {</tspan></text>
<text x="24" y="3246" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java:24 super(</tspan></text>
<text x="24" y="3268" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java:25 &quot;the change stream&#x27;s resume position is no longer in the oplog; consumption st</tspan><tspan x="24" dy="22">opped rather &quot;</tspan></text>
<text x="24" y="3312" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java:26 + &quot;than restarting from now and silently skipping the gap&quot;,</tspan></text>
<text x="24" y="3334" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java:27 failureContext);</tspan></text>
<text x="24" y="3356" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java:28 this.subscriptionProfile = Objects.requireNonNull(subscriptionProfile, &quot;subscripti</tspan><tspan x="24" dy="22">onProfile&quot;);</tspan></text>
<text x="24" y="3400" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeHistoryLostException.java:29 }</tspan></text>
<text x="24" y="3422" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"></tspan></text>
<text x="24" y="3444" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 실제로 history lost 를 다루는 자리</tspan></text>
<text x="24" y="3466" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:50 /** The decision for a failure the platform cannot classify as resumable. */</tspan></text>
<text x="24" y="3488" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:51 public MongoChangeStreamRecoveryDecision onFailure(MongoDriverFailureView failure) {</tspan></text>
<text x="24" y="3510" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:52 Objects.requireNonNull(failure, &quot;failure&quot;);</tspan></text>
<text x="24" y="3532" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:53 if (failure.hasServerCode() &amp;&amp; isHistoryLost(failure.serverCode())) {</tspan></text>
<text x="24" y="3554" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:54 return MongoChangeStreamRecoveryDecision.halt(</tspan></text>
<text x="24" y="3576" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:55 MongoChangeStreamState.HISTORY_LOST, HISTORY_LOST_RUNBOOK);</tspan></text>
<text x="24" y="3598" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:56 }</tspan></text>
<text x="24" y="3620" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:57 if (failure.hasLabel(&quot;ResumableChangeStreamError&quot;)) {</tspan></text>
<text x="24" y="3642" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:58 return MongoChangeStreamRecoveryDecision.resume();</tspan></text>
<text x="24" y="3664" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:59 }</tspan></text>
<text x="24" y="3686" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:60 return MongoChangeStreamRecoveryDecision.halt(MongoChangeStreamState.FAILED, FAILU</tspan><tspan x="24" dy="22">RE_RUNBOOK);</tspan></text>
<text x="24" y="3730" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamRecoveryPolicy.java:61 }</tspan></text>
<text x="24" y="3752" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> 소비자가 그 결정을 받는 자리 :</tspan></text>
<text x="24" y="3774" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ReactiveMongoChangeStreamConsumer.java:119 invalidates.requireCorrectResumeOption(checkpoint, checkpoint.position());</tspan></text>
<text x="24" y="3796" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ReactiveMongoChangeStreamConsumer.java:214 return recovery.onFailure(MongoDriverFailureView.from(driverFailure));</tspan></text>
<text x="24" y="3818" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> history lost 일 때 호출자가 실제로 받는 것 :</tspan></text>
<text x="24" y="3840" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ChangeStreamConsumerLifecycleTest.java:108 </tspan></text>
<text x="24" y="3862" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ChangeStreamConsumerLifecycleTest.java:109 @Test</tspan></text>
<text x="24" y="3884" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ChangeStreamConsumerLifecycleTest.java:110 @DisplayName(&quot;a lost history stops the subscription and names the runbook&quot;)</tspan></text>
<text x="24" y="3906" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ChangeStreamConsumerLifecycleTest.java:111 void aLostHistoryStopsTheSubscription() {</tspan></text>
<text x="24" y="3928" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ChangeStreamConsumerLifecycleTest.java:112 RecordingSource source = new RecordingSource(Flux.error(queryFailure(286, &quot;&quot;)))</tspan><tspan x="24" dy="22">;</tspan></text>
<text x="24" y="3972" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ChangeStreamConsumerLifecycleTest.java:113 ReactiveMongoChangeStreamConsumer consumer = consumer(source);</tspan></text>
<text x="24" y="3994" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ChangeStreamConsumerLifecycleTest.java:114 </tspan></text>
<text x="24" y="4016" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ChangeStreamConsumerLifecycleTest.java:115 StepVerifier.create(consumer.run()).verifyError(MongoQueryException.class);</tspan></text>
<text x="24" y="4038" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ChangeStreamConsumerLifecycleTest.java:116 </tspan></text>
<text x="24" y="4060" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ChangeStreamConsumerLifecycleTest.java:117 assertThat(consumer.state()).isEqualTo(MongoChangeStreamState.HISTORY_LOST);</tspan></text>
<text x="24" y="4082" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ChangeStreamConsumerLifecycleTest.java:118 assertThat(consumer.requiredRunbook())</tspan></text>
<text x="24" y="4104" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ChangeStreamConsumerLifecycleTest.java:119 .isEqualTo(MongoChangeStreamRecoveryPolicy.HISTORY_LOST_RUNBOOK);</tspan></text>
<text x="24" y="4126" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ChangeStreamConsumerLifecycleTest.java:120 assertThat(source.opens)</tspan></text>
<text x="24" y="4148" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ChangeStreamConsumerLifecycleTest.java:121 .as(&quot;restarting from now would hide the gap, not close it&quot;)</tspan></text>
<text x="24" y="4170" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ChangeStreamConsumerLifecycleTest.java:122 .isEqualTo(1);</tspan></text>
<text x="24" y="4192" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ChangeStreamConsumerLifecycleTest.java:123 assertThat(checkpoints.saved).isEmpty();</tspan></text>
<text x="24" y="4214" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ChangeStreamConsumerLifecycleTest.java:124 }</tspan></text>
<text x="24" y="4236" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"></tspan></text>
<text x="24" y="4258" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 자기 자신과 견주는 검사</tspan></text>
<text x="24" y="4280" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java:24 </tspan></text>
<text x="24" y="4302" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java:25 /**</tspan></text>
<text x="24" y="4324" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java:26 * Rejects a checkpoint that would be replayed with the wrong resume option.</tspan></text>
<text x="24" y="4346" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java:27 *</tspan></text>
<text x="24" y="4368" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java:28 * @throws IllegalStateException when an invalidate checkpoint is about to be used with {@co</tspan><tspan x="24" dy="22">de</tspan></text>
<text x="24" y="4412" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java:29 * resumeAfter}</tspan></text>
<text x="24" y="4434" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java:30 */</tspan></text>
<text x="24" y="4456" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java:31 public void requireCorrectResumeOption(</tspan></text>
<text x="24" y="4478" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java:32 MongoResumeCheckpoint checkpoint, MongoResumePosition intended) {</tspan></text>
<text x="24" y="4500" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java:33 Objects.requireNonNull(checkpoint, &quot;checkpoint&quot;);</tspan></text>
<text x="24" y="4522" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java:34 Objects.requireNonNull(intended, &quot;intended&quot;);</tspan></text>
<text x="24" y="4544" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java:35 if (checkpoint.position() != intended) {</tspan></text>
<text x="24" y="4566" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java:36 throw new IllegalStateException(</tspan></text>
<text x="24" y="4588" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java:37 &quot;checkpoint for subscription &#x27;&quot;</tspan></text>
<text x="24" y="4610" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java:38 + checkpoint.subscriptionProfile()</tspan></text>
<text x="24" y="4632" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java:39 + &quot;&#x27; must be replayed with &quot;</tspan></text>
<text x="24" y="4654" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java:40 + checkpoint.position()</tspan></text>
<text x="24" y="4676" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java:41 + &quot; but &quot;</tspan></text>
<text x="24" y="4698" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java:42 + intended</tspan></text>
<text x="24" y="4720" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java:43 + &quot; was requested&quot;);</tspan></text>
<text x="24" y="4742" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java:44 }</tspan></text>
<text x="24" y="4764" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoInvalidateRecovery.java:45 }</tspan></text>
<text x="24" y="4786" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> 그 메서드를 부르는 자리 전부 :</tspan></text>
<text x="24" y="4808" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> main · ReactiveMongoChangeStreamConsumer.java:119 invalidates.requireCorrectResumeOption(checkpoint, checkpoint.position()</tspan><tspan x="24" dy="22">);</tspan></text>
<text x="24" y="4852" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> main · MongoInvalidateRecovery.java:31 public void requireCorrectResumeOption(</tspan></text>
<text x="24" y="4874" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> test · MongoChangeStreamRecoveryPolicyTest.java:59 () -&gt; recovery.requireCorrectResumeOption(checkpoint, MongoResumePositi</tspan><tspan x="24" dy="22">on.RESUME_AFTER))</tspan></text>
<text x="24" y="4918" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"></tspan></text>
<text x="24" y="4940" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 상태 열거형이 그 구분을 어떻게 적는가</tspan></text>
<text x="24" y="4962" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:1 package dev.caskeleton.adapter.outbound.mongo.changestream;</tspan></text>
<text x="24" y="4984" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:2 </tspan></text>
<text x="24" y="5006" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:3 /**</tspan></text>
<text x="24" y="5028" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:4 * The lifecycle state of one change stream subscription (design §20.1).</tspan></text>
<text x="24" y="5050" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:5 *</tspan></text>
<text x="24" y="5072" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:6 * &lt;p&gt;{@code HISTORY_LOST} is separate from {@code FAILED} because it is the one state the platf</tspan><tspan x="24" dy="22">orm</tspan></text>
<text x="24" y="5116" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:7 * refuses to recover from on its own. Resuming from &quot;now&quot; after the oplog has rolled past the</tspan></text>
<text x="24" y="5138" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:8 * stored token silently discards every change in between — the projection then looks healthy a</tspan><tspan x="24" dy="22">nd is</tspan></text>
<text x="24" y="5182" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:9 * quietly wrong, which is worse than a stopped consumer somebody has to look at.</tspan></text>
<text x="24" y="5204" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:10 */</tspan></text>
<text x="24" y="5226" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:11 public enum MongoChangeStreamState {</tspan></text>
<text x="24" y="5248" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:12 </tspan></text>
<text x="24" y="5270" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:13 /** Opening the stream and resolving the resume position. */</tspan></text>
<text x="24" y="5292" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:14 STARTING,</tspan></text>
<text x="24" y="5314" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:15 </tspan></text>
<text x="24" y="5336" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:16 /** Consuming events. */</tspan></text>
<text x="24" y="5358" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:17 RUNNING,</tspan></text>
<text x="24" y="5380" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:18 </tspan></text>
<text x="24" y="5402" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:19 /** Recovering from a resumable failure such as a primary failover. */</tspan></text>
<text x="24" y="5424" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:20 RESUMING,</tspan></text>
<text x="24" y="5446" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:21 </tspan></text>
<text x="24" y="5468" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:22 /** The oplog no longer contains the stored resume position. Consumption stops. */</tspan></text>
<text x="24" y="5490" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:23 HISTORY_LOST,</tspan></text>
<text x="24" y="5512" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:24 </tspan></text>
<text x="24" y="5534" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:25 /** A non-resumable failure. Consumption stops. */</tspan></text>
<text x="24" y="5556" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:26 FAILED,</tspan></text>
<text x="24" y="5578" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:27 </tspan></text>
<text x="24" y="5600" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:28 /** Stopped deliberately. */</tspan></text>
<text x="24" y="5622" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:29 STOPPED;</tspan></text>
<text x="24" y="5644" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:30 </tspan></text>
<text x="24" y="5666" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:31 /** True when the platform may resume without an operator decision. */</tspan></text>
<text x="24" y="5688" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:32 public boolean autoResumable() {</tspan></text>
<text x="24" y="5710" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:33 return this == RUNNING || this == RESUMING || this == STARTING;</tspan></text>
<text x="24" y="5732" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:34 }</tspan></text>
<text x="24" y="5754" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MongoChangeStreamState.java:35 }</tspan></text>
</svg>