본문 바로가기
C.W.K.
Stream
Lesson 05 of 05 · published

History 전에만 Delete 해

~12 min · 삭제, 안전, 참조, 변이

Level 0차가운 용기
0 XP0/37 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

history 가 생기기 전만 지울 수 있어

delete 가 맞는 자리는 한 번도 work 에 쓰이지 않은 mistaken row 를 치우는 경우야. typo name 이나 잘못 만든 test pipeline 처럼 어떤 delegation 도 참조하지 않는 설정은 history 가 아니라 unused configuration 이야.

reference count check 와 delete 는 canonical writer transaction 하나 안에서 일어나야 해. UI 가 count 0 을 보여준 뒤 다른 session 이 queue 할 수 있으니 confirmation screen 의 지식은 이미 늙을 수 있어. writer 가 mutation 순간 다시 판단해야 해.

oneoff 는 참조 0이어도 지우지 못해. foreign key 가 막는 건 referential integrity 고, oneoff existence 는 product invariant 라서 별도 rule 이 필요해. database schema 만으로 모든 domain safety 를 표현할 수 없다는 예야.

거절은 next action 을 알려줘. referenced 면 archive, protected 면 allowed field 만 edit, unused 면 delete 성공이야. unused row 에 delegation history 는 없어도 deletion event 를 남기면 전에 보이던 choice 가 왜 사라졌는지 운영 기록이 설명할 수 있어.

경합을 재현해

client A 가 count 0 을 보고, client B 가 delegation 을 queue 한 다음, A 가 delete 를 눌러. canonical transaction 이 reject 해야 안전이 UI 최신성 말고 writer atomicity 에 기대는 거야.

delete 는 아무 record 도 row 를 가리키지 않을 때만 정직해. 한 번도 쓰이지 않은 configuration mistake 는 깨끗이 없앨 수 있어. delegation 이 참조한 뒤라면 삭제가 evidence 를 고아로 만들어. 그때 archive 를 강제하는 건 관료주의가 아니라 referential integrity 를 product behavior 로 드러낸 거야.

두 세션 경합도 만들어봐. 첫 세션이 reference count 0 을 화면에 띄운 뒤 둘째 세션이 delegation 을 queue 하고, 첫 세션이 delete 를 눌러. canonical transaction 이 다시 검사해 거절해야 맞아. 이 시험이 통과하면 안전은 확인 대화상자의 최신성에 기대지 않고 writer 의 원자적 판단에 기대는 거야. destructive UI 는 설명하고, 데이터 계층은 결정해야 해.

Code

Delete unused rows atomically·python
import sqlite3

con = sqlite3.connect(":memory:")
con.executescript("""
CREATE TABLE pipeline(name TEXT PRIMARY KEY);
CREATE TABLE delegation(id INTEGER PRIMARY KEY, pipeline TEXT REFERENCES pipeline(name));
INSERT INTO pipeline VALUES ('typo-row');
""")
with con:
    refs = con.execute("SELECT count(*) FROM delegation WHERE pipeline=?", ("typo-row",)).fetchone()[0]
    if refs:
        raise RuntimeError("archive referenced pipeline")
    con.execute("DELETE FROM pipeline WHERE name=?", ("typo-row",))
assert con.execute("SELECT count(*) FROM pipeline").fetchone()[0] == 0

External links

Exercise

protected, referenced, archived, unused 행의 삭제 결정표를 써. 각각 허용 동작과 사용자 안내를 넣어.
Hint
둘 다 거절이어도 protected 와 referenced 는 다른 이유야.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고
💛 by 피파warm

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.