Files
document-haness/docs/clean-architecture-backend-template/final/evidence/rendered/a-lease-without-an-owner.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

89 lines
22 KiB
XML

<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="2130" viewBox="0 0 1200 2130" 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="2128" 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">$ O=messaging/messaging-outbox-jdbc-postgresql/src/main; M=$O/resources/db/migration/messaging/V2__messaging_outbox_leas</tspan><tspan x="24" dy="22">e_fencing.sql; R=$O/java/dev/caskeleton/messaging/outbox/JdbcOutboxRepository.java; I=messaging/messaging-reliability-ap</tspan><tspan x="24" dy="22">i/src/main/java/dev/caskeleton/messaging/reliability/OutboxRepository.java; echo &#x27;# V2 가 더한 컬럼과 제약&#x27;; sed -n &#x27;15,</tspan><tspan x="24" dy="22">23p&#x27; $M; echo; echo &#x27;# 다섯 상태에서 여섯으로&#x27;; grep -n &quot;status IN&quot; $O/resources/db/migration/messaging/V1__messaging_ou</tspan><tspan x="24" dy="22">tbox.sql | head -1; sed -n &#x27;33p&#x27; $M; echo; echo &#x27;# 청구가 소유자와 토큰을 같은 문장에서 쓴다&#x27;; sed -n &#x27;129,133p&#x27; $R; ech</tspan><tspan x="24" dy="22">o &#x27;# 그 청구가 읽는 술어&#x27;; sed -n &#x27;117,124p&#x27; $R; echo &#x27;# V2 가 그 술어에 맞춰 만든 부분 인덱스&#x27;; sed -n &#x27;37,39p&#x27; $M;</tspan><tspan x="24" dy="22"> echo; echo &#x27;# 최종 쓰기는 소유자와 토큰을 조건으로 걸고, 0행을 삼키지 않는다&#x27;; grep -n &quot;AND lease_owner = ? AND lease_t</tspan><tspan x="24" dy="22">oken = ?&quot; $R; sed -n &#x27;394,396p&#x27; $R; echo; echo &#x27;# 릴레이가 부르는 것은 전부 신세대다&#x27;; grep -rn &#x27;repository\.\(mark\|rel</tspan><tspan x="24" dy="22">ease\|claim\|lease\)&#x27; --include=*.java $O/java | sed &#x27;s|.*/||&#x27;; echo; echo &#x27;# 펜싱 없는 옛 경로는 인터페이스에 남아 있다</tspan><tspan x="24" dy="22">&#x27;; grep -n &#x27;List&lt;OutboxRecord&gt; leaseBatch&#x27; $I; echo &#x27;# 그 메서드 자신의 javadoc 은 아직 안전을 주장한다&#x27;; sed -n &#x27;27,2</tspan><tspan x="24" dy="22">9p&#x27; $I; echo &#x27;# 폐기를 적은 것은 신세대 쪽 javadoc 이다&#x27;; sed -n &#x27;41,44p&#x27; $I; echo -n &#x27;# messaging 트리 전체의 @Depr</tspan><tspan x="24" dy="22">ecated 매치: &#x27;; grep -rn &#x27;@Deprecated&#x27; --include=*.java messaging/ | wc -l; echo -n &#x27;# .leaseBatch( 를 부르는 main 코</tspan><tspan x="24" dy="22">드: &#x27;; grep -rn &#x27;\.leaseBatch(&#x27; --include=*.java . | grep -c &#x27;/main/&#x27;; echo; echo &#x27;# 두 세대가 AMBIGUOUS 에서 남기는 것</tspan><tspan x="24" dy="22">이 다르다&#x27;; sed -n &#x27;332,334p&#x27; $R; echo &#x27; ---구세대&#x27;; sed -n &#x27;438,439p&#x27; $R; echo; echo &#x27;# 같은 형태가 다른 곳에도 있었다</tspan><tspan x="24" dy="22">고 파일서버 마이그레이션이 적는다&#x27;; grep -n &#x27;notification dispatcher&#x27; adapter/outbound/persistence-jpa/src/main/resource</tspan><tspan x="24" dy="22">s/db/migration/jpa/fileserver/V3__fileserver_fenced_cleanup_lease.sql</tspan></text>
<text x="24" y="420" 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/src</tspan></text>
<text x="24" y="442" 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-02T01:32:03+00:00 · exit 0</tspan></text>
<line x1="24" y1="456" x2="1176" y2="456" stroke="#30363d"/>
<text x="24" y="496" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># V2 가 더한 컬럼과 제약</tspan></text>
<text x="24" y="518" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">ALTER TABLE messaging_outbox</tspan></text>
<text x="24" y="540" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ADD COLUMN lease_owner VARCHAR(160),</tspan></text>
<text x="24" y="562" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ADD COLUMN lease_token BIGINT NOT NULL DEFAULT 0,</tspan></text>
<text x="24" y="584" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ADD COLUMN next_attempt_at TIMESTAMPTZ;</tspan></text>
<text x="24" y="606" 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="628" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">-- Backfill is unnecessary for correctness — the default is 0 and the first claim increments it —</tspan></text>
<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">-- but the constraint states the invariant the code depends on.</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">ALTER TABLE messaging_outbox</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"> ADD CONSTRAINT ck_messaging_outbox_lease_token CHECK (lease_token &gt;= 0);</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"></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"># 다섯 상태에서 여섯으로</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">23: CHECK (status IN (&#x27;PENDING&#x27;, &#x27;IN_FLIGHT&#x27;, &#x27;PUBLISHED&#x27;, &#x27;AMBIGUOUS&#x27;, &#x27;FAILED&#x27;)),</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"> CHECK (status IN (&#x27;PENDING&#x27;, &#x27;IN_FLIGHT&#x27;, &#x27;PUBLISHED&#x27;, &#x27;AMBIGUOUS&#x27;, &#x27;FAILED&#x27;, &#x27;EXHAUSTED&#x27;));</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"></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"># 청구가 소유자와 토큰을 같은 문장에서 쓴다</tspan></text>
<text x="24" y="848" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> UPDATE messaging_outbox o</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"> SET status = &#x27;IN_FLIGHT&#x27;,</tspan></text>
<text x="24" y="892" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> lease_expires_at = ?,</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"> lease_owner = ?,</tspan></text>
<text x="24" y="936" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> lease_token = o.lease_token + 1</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"># 그 청구가 읽는 술어</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"> WHERE status IN (&#x27;PENDING&#x27;, &#x27;AMBIGUOUS&#x27;, &#x27;IN_FLIGHT&#x27;)</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"> AND (lease_expires_at IS NULL OR lease_expires_at &lt;= ?)</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"> -- The retry clock lives in the row, not in the relay&#x27;s memory. Without these two</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"> -- predicates an AMBIGUOUS row became claimable again on the very next pass, so a</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"> -- broker outage meant the whole backlog was republished every poll interval and the</tspan></text>
<text x="24" y="1090" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> -- configured attempt budget was a number nothing consulted.</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"> AND (next_attempt_at IS NULL OR next_attempt_at &lt;= ?)</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"> AND attempts &lt; ?</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"># V2 가 그 술어에 맞춰 만든 부분 인덱스</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">CREATE INDEX ix_messaging_outbox_next_attempt</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"> ON messaging_outbox (next_attempt_at, created_at)</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"> WHERE status IN (&#x27;PENDING&#x27;, &#x27;AMBIGUOUS&#x27;, &#x27;IN_FLIGHT&#x27;);</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"></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"># 최종 쓰기는 소유자와 토큰을 조건으로 걸고, 0행을 삼키지 않는다</tspan></text>
<text x="24" y="1288" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">354: + &quot;WHERE message_id = ? AND status = &#x27;IN_FLIGHT&#x27; AND lease_owner = ? AND lease_token = ?&quot;;</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">403: + &quot;WHERE message_id = ? AND status = &#x27;IN_FLIGHT&#x27; AND lease_owner = ? AND lease_token = ?&quot;;</tspan></text>
<text x="24" y="1332" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> * past its lease writes nothing: another relay&#x27;s claim incremented the token, and this update</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"> * matches zero rows. Zero is reported rather than swallowed — a stale write means this worker may</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"> * have produced a duplicate publication, which is exactly what an operator needs to see.</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"></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"># 릴레이가 부르는 것은 전부 신세대다</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">OutboxRelay.java:158: repository.claimBatch(owner, batchSize, leaseDuration, now, scheduler.maxAttempts());</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">OutboxRelay.java:171: if (repository.markPublished(lease, now) == OutboxTransitionResult.APPLIED) {</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">OutboxRelay.java:189: .map(reason -&gt; repository.markExhausted(lease, reason, now))</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">OutboxRelay.java:192: repository.markAmbiguous(</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">OutboxRelay.java:205: if (repository.markFailed(</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"></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"># 펜싱 없는 옛 경로는 인터페이스에 남아 있다</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">36: List&lt;OutboxRecord&gt; leaseBatch(int batchSize, Duration leaseDuration, Instant now);</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"># 그 메서드 자신의 javadoc 은 아직 안전을 주장한다</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"> * &lt;p&gt;Leasing rather than simply selecting is what makes multiple relay instances safe: a record</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"> * claimed by one relay is invisible to the others until its lease expires, so the same message is</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"> * not published concurrently by two processes.</tspan></text>
<text x="24" y="1706" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 폐기를 적은 것은 신세대 쪽 javadoc 이다</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"> * &lt;p&gt;The token is what a terminal write is checked against. {@link #leaseBatch} returns records</tspan></text>
<text x="24" y="1750" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> * without one, so its callers cannot prove a write belongs to their claim; it remains for</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"> * inspection paths and is deprecated for the relay&#x27;s use.</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"> *</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"># messaging 트리 전체의 @Deprecated 매치: 0</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"># .leaseBatch( 를 부르는 main 코드: 0</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"></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"># 두 세대가 AMBIGUOUS 에서 남기는 것이 다르다</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"> &quot;UPDATE messaging_outbox SET status = &#x27;AMBIGUOUS&#x27;, lease_expires_at = NULL, &quot;</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"> + &quot;lease_owner = NULL, last_failure_code = ?, attempts = attempts + 1, &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"> + &quot;next_attempt_at = ? &quot;,</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"> ---구세대</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"> &quot;UPDATE messaging_outbox SET status = &#x27;AMBIGUOUS&#x27;, lease_expires_at = NULL, &quot;</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"> + &quot;last_failure_code = ?, attempts = attempts + 1 WHERE message_id = ?&quot;,</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"></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"># 같은 형태가 다른 곳에도 있었다고 파일서버 마이그레이션이 적는다</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">12:-- part-way through — the same fenced-lease problem the notification dispatcher had.</tspan></text>
</svg>