이번 파이프라인 작업과 무관하게 작업 트리에 남아 있던 것을 그대로 올린다. 사용자가 「전부 커밋」으로 정했고, 이번 작업과 섞이지 않게 커밋만 나눴다. 대부분은 clean-architecture-backend-template 의 그림 정본 재배치다 — final/assets/diagrams/<이름>/ 에 있던 것이 CLAUDE.md 가 적은 배치인 final/assets/<이름>/ 로 옮겨졌고 .techviz/<이름>/ 이 함께 들어왔다. 삽입 줄의 대부분(3.15M)이 그 .techviz context.json 이다. 그 밖에 ca-tmpl·document-haness 의 정리, .claude/agents/ 열한 개, writing-practitioner-guides 스킬, .playwright-mcp 세션 산출물, scripts/check-ssot-facts.py 와 그 시험이 들어 있다. 이 커밋의 내용은 내가 만든 것이 아니라 이전 세션이 남긴 것이고 검증하지 않았다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
65 lines
2.9 KiB
Markdown
65 lines
2.9 KiB
Markdown
---
|
|
kind: REFERENCE
|
|
slug: cas-tuple-in-the-where-clause
|
|
title: CAS 튜플을 where 절에 전부 반복하고 update count를 답으로 쓴다
|
|
topic: owner-safe-state-machines
|
|
project: clean-architecture-backend-template
|
|
status: 게시 전
|
|
sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
|
|
rootTreeNode: reference:cas-tuple-in-the-where-clause
|
|
verifiedOn: # 이 기록은 이번 회차에 실행 확인을 하지 않았다
|
|
---
|
|
|
|
# CAS 튜플을 where 절에 전부 반복하고 update count를 답으로 쓴다
|
|
|
|
행을 읽고 나서 갱신하는 형태를 없애, 리스가 만료된 작업자가 인계받은 작업자의 상태를 덮는 것을 막는다. 소유자 튜플 전체를 where 절에 반복하고 갱신 건수를 답으로 받으며, 0 건은 예외가 아니라 정상 경로다.
|
|
|
|
## 목적
|
|
|
|
행을 읽고 나서 갱신하는 형태를 없애, 리스가 만료된 작업자가 인계받은 작업자의 상태를 덮는 것을 막는다.
|
|
|
|
## 규칙
|
|
|
|
1. 소유자 튜플 전체를 where 절에 반복한다
|
|
스코프만으로 갱신하지 않는다. 소유자와 토큰과 시도와 상태 리비전을 전부 조건에 넣는다.
|
|
|
|
2. 갱신 건수가 답이다
|
|
한 건이면 이 소유자가 이 리비전에서 여전히 소유자였다는 뜻이고, 0 이면 다른 무언가가 레코드를 움직였다는 뜻이다.
|
|
|
|
3. 0 건은 예외가 아니라 정상 경로다
|
|
경합을 예외 처리로 다루면 그 경로가 테스트되지 않는다. 건수를 값으로 받아 호출자가 해석한다.
|
|
|
|
4. 전이마다 상태 리비전을 올린다
|
|
소유권만으로는 부족하다. 자기가 본 시점까지 맞아야 한다.
|
|
|
|
5. 같은 가드를 쓰는 문장을 한 자리에 모은다
|
|
흩어져 있으면 그중 하나가 조건을 짧게 쓰는 것을 막을 수 없다.
|
|
|
|
## 적용 조건
|
|
|
|
여러 작업자가 같은 행을 놓고 경합하는 모든 상태 기계
|
|
|
|
리스나 청구로 소유권을 표현하는 테이블
|
|
|
|
## 예외
|
|
|
|
단일 작업자만 접근하는 것이 구조적으로 보장되는 테이블은 대상이 아니다. 그 보장이 무엇인지 적혀 있어야 한다.
|
|
|
|
## 예시
|
|
|
|
멱등성 전이 문장들이 스코프와 토큰과 시도와 청구 연산과 상태 리비전을 전부 조건에 반복한다.
|
|
|
|
outbox 폴링 전달 어댑터의 완료 문장 셋이 같은 형태다.
|
|
|
|
네이티브 청구 문장이 JPA 버전 컬럼을 함께 올린다. 그러지 않으면 청구 이전에 로드된 엔티티의 플러시가 청구를 덮는다.
|
|
|
|
## 관계
|
|
|
|
- **CAS 튜플과 update count가 답이 되는 구조**
|
|
이 규칙이 나온 개념이다.
|
|
- **lease가 만료 시각만 기록하고 소유자를 기록하지 않아 terminal state가 되돌려졌다**
|
|
이 규칙이 없을 때의 결과다.
|
|
- **native claim이 Version을 올리지 않아 충돌을 보고하지 않는 낙관적 잠금이 됐다**
|
|
튜플을 반복해도 다른 잠금 장치와 어긋날 수 있다는 사례다.
|
|
|