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>
61 lines
2.6 KiB
Markdown
61 lines
2.6 KiB
Markdown
---
|
|
kind: REFERENCE
|
|
slug: claim-with-a-conditional-update-not-a-read
|
|
title: 조건부 update로 행을 claim하고 읽은 값으로 판단하지 않는다
|
|
topic: fileserver-state-and-fencing
|
|
project: clean-architecture-backend-template
|
|
status: 게시 전
|
|
sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
|
|
rootTreeNode: reference:claim-with-a-conditional-update-not-a-read
|
|
verifiedOn: # 이 기록은 이번 회차에 실행 확인을 하지 않았다
|
|
---
|
|
|
|
# 조건부 update로 행을 claim하고 읽은 값으로 판단하지 않는다
|
|
|
|
## 목적
|
|
|
|
읽기와 행동 사이에 상태가 바뀌어, 이미 유효하지 않은 판단으로 되돌릴 수 없는 작업을 수행하는 것을 막는다.
|
|
|
|
## 규칙
|
|
|
|
1. 읽고 나서 판단하지 않는다
|
|
조건을 갱신문의 where 절에 넣고 갱신 건수로 판단한다.
|
|
|
|
2. 되돌릴 수 없는 작업 앞에서는 특히 그렇다
|
|
물리 삭제나 외부 호출은 되돌릴 수 없다. 그 앞의 판단은 원자적이어야 한다.
|
|
|
|
3. 양쪽이 같은 사실을 본다
|
|
한쪽은 리스의 부재를 보고 다른 쪽은 만료만 보면, 둘 다 자기 기준으로 옳으면서 서로 어긋난다.
|
|
|
|
4. 상태를 명시적으로 만든다
|
|
끝났다는 사실이 값으로 없으면 각 참여자가 그것을 추론하고, 추론의 근거가 서로 다르다.
|
|
|
|
5. 청구하지 못하면 미룬다
|
|
갱신 건수가 0 이면 다른 참여자가 그 행을 들고 있다는 뜻이다. 강제하지 않고 다음 주기로 넘긴다.
|
|
|
|
## 적용 조건
|
|
|
|
여러 참여자가 같은 자원을 놓고 경합하는 정리 작업과 배치
|
|
|
|
물리 삭제나 외부 호출이 뒤따르는 판정
|
|
|
|
## 예외
|
|
|
|
읽기와 행동이 같은 트랜잭션 안에서 행 잠금과 함께 일어나면 조건부 갱신 없이도 안전하다. 그 잠금이 실제로 걸리는지 확인해야 한다.
|
|
|
|
## 예시
|
|
|
|
정리가 쓰기 리스를 읽어 없음을 확인하고 스테이징 바이트를 지웠다. 읽기와 삭제 사이에 쓰기 작업자가 그 리스를 얻었고, 지워진 것은 업로드가 이어 쓰고 있던 객체였다.
|
|
|
|
수정 후 정리는 조건부 갱신으로 청구하고, 리스가 실제로 걸려 있으면 아무것도 청구하지 않고 미룬다.
|
|
|
|
## 관계
|
|
|
|
- **cleanup이 읽은 lease와 삭제 사이에 writer가 그 lease를 얻을 수 있었다**
|
|
이 규칙을 만든 사례다.
|
|
- **CAS 튜플을 where 절에 전부 반복하고 update count를 답으로 쓴다**
|
|
같은 규칙의 상태 기계 판이다.
|
|
- **시간은 DB에서, 그리고 행을 잠근 다음에 읽는다**
|
|
같은 계열의 짝 규칙이다.
|
|
|