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

192 lines
37 KiB
XML

<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="3758" viewBox="0 0 1200 3758" 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="3756" 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
hits() {
local out rc
out=$(</tspan><tspan x="24" dy="22">git grep -nE &quot;$1&quot; -- &quot;$2&quot;) &amp;&amp; rc=0 || rc=$?
[ &quot;$rc&quot; -le 1 ] || { echo &quot;SEARCH FAILED rc=$rc : $1&quot; &gt;&amp;2; return 2; }
[</tspan><tspan x="24" dy="22"> &quot;$rc&quot; -eq 0 ] &amp;&amp; printf &#x27;%s\n&#x27; &quot;$out&quot; || true
}
mod() { sed -E &#x27;s#^src/(.*)/src/([a-zA-Z]+)/java/.*/([A-Za-z]+\.java):(</tspan><tspan x="24" dy="22">[0-9]+): *# \1 · \2 · \3:\4 #&#x27;; }
at() { awk -v s=&quot;$2&quot; -v e=&quot;$3&quot; -v n=&quot;$4&quot; &#x27;NR&gt;=s &amp;&amp; NR&lt;=e {printf &quot; %s:%d %s\n&quot;, n</tspan><tspan x="24" dy="22">, NR, $0}&#x27; &quot;$1&quot;; }
G=src/adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/file</tspan><tspan x="24" dy="22">server/JpaQuotaReclaimGateway.java
R=src/adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/</tspan><tspan x="24" dy="22">persistence/fileserver/repository/FileserverQuotaRepository.java
test -f &quot;$G&quot; &amp;&amp; test -f &quot;$R&quot;
echo &quot;# 회수 게이트웨이 </tspan><tspan x="24" dy="22">전문 ($(wc -l &lt; &quot;$G&quot;) 줄)&quot;
awk &#x27;{printf &quot; JpaQuotaReclaimGateway.java:%d %s\n&quot;, NR, $0}&#x27; &quot;$G&quot;
echo
echo &quot;# 그 한 번의 </tspan><tspan x="24" dy="22">질의가 무엇을 돌려주는가&quot;
at &quot;$R&quot; 106 117 FileserverQuotaRepository.java
echo
echo &quot;# 그 차감이 0 행을 갱신했을 때 무엇</tspan><tspan x="24" dy="22">이 되는가&quot;
at &quot;$R&quot; 119 139 FileserverQuotaRepository.java
echo
echo &quot;# 회수를 부르는 자리&quot;
hits &#x27;\.reclaim\(&#x27; &#x27;src/**/*</tspan><tspan x="24" dy="22">.java&#x27; | mod
echo
echo &quot;# 같은 게이트웨이를 그대로 부른 결과 (리포지터리만 프록시)&quot;
grep -nE &#x27;RECLAIM|findCommittedWith</tspan><tspan x="24" dy="22">Bytes|reduceCommitted|committedRow|gateway.reclaim|new JpaQuotaReclaimGateway|subList|ledger.add&#x27; \
/tmp/probe-reclaim</tspan><tspan x="24" dy="22">/ReclaimProbe.java | sed -E &#x27;s#^([0-9]+): *# probe:\1 #&#x27;
CP=$(cat /tmp/cp-jpa.txt)
rm -rf /tmp/probe-reclaim/out &amp;&amp; </tspan><tspan x="24" dy="22">mkdir -p /tmp/probe-reclaim/out
javac -nowarn -cp &quot;$CP&quot; -d /tmp/probe-reclaim/out /tmp/probe-reclaim/ReclaimProbe.java
j</tspan><tspan x="24" dy="22">ava -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 \
-cp &quot;$CP:/tmp/probe-reclaim/out&quot; dev.caskeleton.adapter.outbou</tspan><tspan x="24" dy="22">nd.persistence.fileserver.ReclaimProbe
echo
echo &quot;# 그 경계를 짚는 시험이 있는가&quot;
for n in 64 65 RECLAIM_PAGE; do
pri</tspan><tspan x="24" dy="22">ntf &#x27; 시험에서 %s 를 쓰는 줄 : %s 개\n&#x27; &quot;$n&quot; \
&quot;$({ git grep -nE &quot;\\b$n\\b&quot; -- &#x27;src/**/*Reclaim*&#x27; &#x27;src/**/*Quota*&#x27; </tspan><tspan x="24" dy="22">|| true; } | { grep -E &#x27;/src/(test|[a-zA-Z]+Test)/&#x27; || true; } | grep -c . || true)&quot;
done
echo &quot; 회수를 다루는 시험 파</tspan><tspan x="24" dy="22">일 :&quot;
git ls-files -- &#x27;src/**/*Reclaim*&#x27; | sed &#x27;s#^# #&#x27;
</tspan></text>
<text x="24" y="486" 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="508" 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-04T06:08:26+00:00 · exit 0</tspan></text>
<line x1="24" y1="522" x2="1176" y2="522" stroke="#30363d"/>
<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"># 회수 게이트웨이 전문 (64 줄)</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"> JpaQuotaReclaimGateway.java:1 package dev.caskeleton.adapter.outbound.persistence.fileserver;</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"> JpaQuotaReclaimGateway.java:2 </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"> JpaQuotaReclaimGateway.java:3 import dev.caskeleton.adapter.outbound.persistence.fileserver.entity.QuotaReservationEntity;</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"> JpaQuotaReclaimGateway.java:4 import dev.caskeleton.adapter.outbound.persistence.fileserver.repository.FileserverQuotaReposito</tspan><tspan x="24" dy="22">ry;</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"> JpaQuotaReclaimGateway.java:5 import dev.caskeleton.application.fileserver.api.metadata.QuotaScope;</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"> JpaQuotaReclaimGateway.java:6 import dev.caskeleton.application.fileserver.cleanup.QuotaReclaimGateway;</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"> JpaQuotaReclaimGateway.java:7 import java.time.Clock;</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"> JpaQuotaReclaimGateway.java:8 import java.time.Instant;</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"> JpaQuotaReclaimGateway.java:9 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;</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"> JpaQuotaReclaimGateway.java:10 import org.springframework.data.domain.Limit;</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"> JpaQuotaReclaimGateway.java:11 import org.springframework.stereotype.Repository;</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"> JpaQuotaReclaimGateway.java:12 </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"> JpaQuotaReclaimGateway.java:13 /**</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"> JpaQuotaReclaimGateway.java:14 * Returns reclaimed bytes to a scope&#x27;s committed total.</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"> JpaQuotaReclaimGateway.java:15 *</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"> JpaQuotaReclaimGateway.java:16 * &lt;p&gt;Committed usage is spread over many rows, so a reclaim is drawn down newest-first across </tspan><tspan x="24" dy="22">them</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"> JpaQuotaReclaimGateway.java:17 * until the amount is satisfied. Newest-first matters: the most recently committed rows are th</tspan><tspan x="24" dy="22">e</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"> JpaQuotaReclaimGateway.java:18 * ones a delete is most likely to correspond to, and drawing from them keeps historical rows f</tspan><tspan x="24" dy="22">rom</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"> JpaQuotaReclaimGateway.java:19 * being hollowed out by unrelated deletions.</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"> JpaQuotaReclaimGateway.java:20 *</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"> JpaQuotaReclaimGateway.java:21 * &lt;p&gt;Each draw-down is conditional on the row still holding at least that many bytes, so two</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"> JpaQuotaReclaimGateway.java:22 * cleanup workers reclaiming at once cannot push the ledger negative — the loser simply moves</tspan><tspan x="24" dy="22"> to</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"> JpaQuotaReclaimGateway.java:23 * the next row.</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"> JpaQuotaReclaimGateway.java:24 *</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"> JpaQuotaReclaimGateway.java:25 * &lt;p&gt;A remainder that no row can absorb is dropped rather than carried. The ledger&#x27;s floor is </tspan><tspan x="24" dy="22">zero:</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"> JpaQuotaReclaimGateway.java:26 * a scope cannot owe negative bytes, and a reclaim that outruns the recorded total means the t</tspan><tspan x="24" dy="22">otal</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"> JpaQuotaReclaimGateway.java:27 * was already understated, which a negative balance would not fix.</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"> JpaQuotaReclaimGateway.java:28 */</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"> JpaQuotaReclaimGateway.java:29 @Repository</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"> JpaQuotaReclaimGateway.java:30 @ConditionalOnProperty(prefix = &quot;app.fileserver-platform&quot;, name = &quot;enabled&quot;, havingValue = &quot;tru</tspan><tspan x="24" dy="22">e&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"> JpaQuotaReclaimGateway.java:31 public class JpaQuotaReclaimGateway implements QuotaReclaimGateway {</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"> JpaQuotaReclaimGateway.java:32 </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"> JpaQuotaReclaimGateway.java:33 private static final Limit RECLAIM_PAGE = Limit.of(64);</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"> JpaQuotaReclaimGateway.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"> JpaQuotaReclaimGateway.java:35 private final FileserverQuotaRepository reservations;</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"> JpaQuotaReclaimGateway.java:36 private final Clock clock;</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"> JpaQuotaReclaimGateway.java:37 </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"> JpaQuotaReclaimGateway.java:38 public JpaQuotaReclaimGateway(FileserverQuotaRepository reservations, Clock clock) {</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"> JpaQuotaReclaimGateway.java:39 this.reservations = reservations;</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"> JpaQuotaReclaimGateway.java:40 this.clock = clock;</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"> JpaQuotaReclaimGateway.java:41 }</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"> JpaQuotaReclaimGateway.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"> JpaQuotaReclaimGateway.java:43 @Override</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"> JpaQuotaReclaimGateway.java:44 public void reclaim(QuotaScope scope, long bytes) {</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"> JpaQuotaReclaimGateway.java:45 if (bytes &lt; 0) {</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"> JpaQuotaReclaimGateway.java:46 throw new IllegalArgumentException(&quot;bytes must not be negative&quot;);</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"> JpaQuotaReclaimGateway.java:47 }</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"> JpaQuotaReclaimGateway.java:48 if (bytes == 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"> JpaQuotaReclaimGateway.java:49 return;</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"> JpaQuotaReclaimGateway.java:50 }</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"> JpaQuotaReclaimGateway.java:51 Instant now = clock.instant();</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"> JpaQuotaReclaimGateway.java:52 long outstanding = bytes;</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"> JpaQuotaReclaimGateway.java:53 for (QuotaReservationEntity committed :</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"> JpaQuotaReclaimGateway.java:54 reservations.findCommittedWithBytes(scope.type(), scope.value(), RECLAIM_PAGE)) {</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"> JpaQuotaReclaimGateway.java:55 if (outstanding == 0) {</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"> JpaQuotaReclaimGateway.java:56 return;</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"> JpaQuotaReclaimGateway.java:57 }</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"> JpaQuotaReclaimGateway.java:58 long draw = Math.min(outstanding, committed.getCommittedBytes());</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"> JpaQuotaReclaimGateway.java:59 if (reservations.reduceCommitted(committed.getReservationId(), draw, now) == 1) {</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"> JpaQuotaReclaimGateway.java:60 outstanding -= draw;</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"> JpaQuotaReclaimGateway.java:61 }</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"> JpaQuotaReclaimGateway.java:62 }</tspan></text>
<text x="24" y="2124" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> JpaQuotaReclaimGateway.java:63 }</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"> JpaQuotaReclaimGateway.java:64 }</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"></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"># 그 한 번의 질의가 무엇을 돌려주는가</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"> FileserverQuotaRepository.java:106 /** Committed rows for a scope that still carry bytes, newest first. */</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"> FileserverQuotaRepository.java:107 @Query(</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"> FileserverQuotaRepository.java:108 &quot;&quot;&quot;</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"> FileserverQuotaRepository.java:109 select q from QuotaReservationEntity q</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"> FileserverQuotaRepository.java:110 where q.scopeType = :scopeType</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"> FileserverQuotaRepository.java:111 and q.scopeValue = :scopeValue</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"> FileserverQuotaRepository.java:112 and q.status = &#x27;COMMITTED&#x27;</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"> FileserverQuotaRepository.java:113 and q.committedBytes &gt; 0</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"> FileserverQuotaRepository.java:114 order by q.updatedAt desc</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"> FileserverQuotaRepository.java:115 &quot;&quot;&quot;)</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"> FileserverQuotaRepository.java:116 List&lt;QuotaReservationEntity&gt; findCommittedWithBytes(</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"> FileserverQuotaRepository.java:117 @Param(&quot;scopeType&quot;) String scopeType, @Param(&quot;scopeValue&quot;) String scopeValue, Limit l</tspan><tspan x="24" dy="22">imit);</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"></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"># 그 차감이 0 행을 갱신했을 때 무엇이 되는가</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"> FileserverQuotaRepository.java:119 /**</tspan></text>
<text x="24" y="2564" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> FileserverQuotaRepository.java:120 * Gives back part of a committed row.</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"> FileserverQuotaRepository.java:121 *</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"> FileserverQuotaRepository.java:122 * &lt;p&gt;The guard is what makes concurrent reclaims safe: a row that another reclaim alread</tspan><tspan x="24" dy="22">y drew</tspan></text>
<text x="24" y="2652" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> FileserverQuotaRepository.java:123 * down below {@code amount} updates zero rows, and the caller moves to the next row inst</tspan><tspan x="24" dy="22">ead of</tspan></text>
<text x="24" y="2696" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> FileserverQuotaRepository.java:124 * driving the ledger negative.</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"> FileserverQuotaRepository.java:125 */</tspan></text>
<text x="24" y="2740" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> FileserverQuotaRepository.java:126 @Modifying(clearAutomatically = true, flushAutomatically = true)</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"> FileserverQuotaRepository.java:127 @Query(</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"> FileserverQuotaRepository.java:128 &quot;&quot;&quot;</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"> FileserverQuotaRepository.java:129 update QuotaReservationEntity q</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"> FileserverQuotaRepository.java:130 set q.committedBytes = q.committedBytes - :amount,</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"> FileserverQuotaRepository.java:131 q.version = q.version + 1,</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"> FileserverQuotaRepository.java:132 q.updatedAt = :now</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"> FileserverQuotaRepository.java:133 where q.reservationId = :reservationId</tspan></text>
<text x="24" y="2916" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> FileserverQuotaRepository.java:134 and q.committedBytes &gt;= :amount</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"> FileserverQuotaRepository.java:135 &quot;&quot;&quot;)</tspan></text>
<text x="24" y="2960" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> FileserverQuotaRepository.java:136 int reduceCommitted(</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"> FileserverQuotaRepository.java:137 @Param(&quot;reservationId&quot;) UUID reservationId,</tspan></text>
<text x="24" y="3004" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> FileserverQuotaRepository.java:138 @Param(&quot;amount&quot;) long amount,</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"> FileserverQuotaRepository.java:139 @Param(&quot;now&quot;) Instant now);</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"></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"># 회수를 부르는 자리</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"> adapter/outbound/persistence-jpa · postgresqlIntegrationTest · PostgreSqlFileserverReclamationIntegrationTest.java:341 quot</tspan><tspan x="24" dy="22">aReclaim.reclaim(scope, 800);</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"> adapter/outbound/persistence-jpa · postgresqlIntegrationTest · PostgreSqlFileserverReclamationIntegrationTest.java:361 quot</tspan><tspan x="24" dy="22">aReclaim.reclaim(scope, 5_000);</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"> application-core · main · DefaultCleanupService.java:185 quotaGateway.reclaim(QuotaScope.ofNamespace(record.namespace().val</tspan><tspan x="24" dy="22">ue()), size);</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"></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"># 같은 게이트웨이를 그대로 부른 결과 (리포지터리만 프록시)</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"> probe:22 static QuotaReservationEntity committedRow(long bytes) {</tspan></text>
<text x="24" y="3290" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> probe:42 ledger.add(committedRow(1));</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"> probe:51 case &quot;findCommittedWithBytes&quot; -&gt; {</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"> probe:54 return ledger.subList(0, Math.min(limit, ledger.size()));</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"> probe:56 case &quot;reduceCommitted&quot; -&gt; {</tspan></text>
<text x="24" y="3378" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> probe:76 new JpaQuotaReclaimGateway(repo, Clock.fixed(Instant.EPOCH, ZoneOffset.UTC));</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"> probe:77 gateway.reclaim(new QuotaScope(&quot;NAMESPACE&quot;, &quot;probe&quot;), askedBytes);</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"> JpaQuotaReclaimGateway.reclaim 을 그대로 부른 결과</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"> 원장에 1바이트 확정 행 64 개 · 64 바이트 회수 요청 → 페이지 질의 1 회 · 차감 64 회 · 회수 못한 바이트 0</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"> 원장에 1바이트 확정 행 65 개 · 65 바이트 회수 요청 → 페이지 질의 1 회 · 차감 64 회 · 회수 못한 바이트 1</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"> 원장에 1바이트 확정 행 200 개 · 200 바이트 회수 요청 → 페이지 질의 1 회 · 차감 64 회 · 회수 못한 바이트 136</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"></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"># 그 경계를 짚는 시험이 있는가</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"> 시험에서 64 를 쓰는 줄 : 0 개</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"> 시험에서 65 를 쓰는 줄 : 0 개</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"> 시험에서 RECLAIM_PAGE 를 쓰는 줄 : 0 개</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"> 회수를 다루는 시험 파일 :</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"> src/adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/fileserver/JpaQuotaReclaimGat</tspan><tspan x="24" dy="22">eway.java</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"> src/application-core/src/main/java/dev/caskeleton/application/fileserver/cleanup/QuotaReclaimGateway.java</tspan></text>
<text x="24" y="3708" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> src/application-core/src/test/java/dev/caskeleton/application/fileserver/testkit/RecordingQuotaReclaimGateway.java</tspan></text>
</svg>