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

앞쪽 봉인과 뒤쪽 봉인

~12 min · guardrails, pipelines, design, scoping

Level 0젖은 흙
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

깃발 하나가 일을 둘 하고 있었어

봉인의 첫 판은 파이프라인에 묶여 있었어. 파이프라인이 제한되거나 안 되거나 둘 중 하나였고, 깃발 하나가 가드를 세우는 일이랑 아무것도 안 쓰였는지 확인하는 사후 게이트를 모는 일을 같이 했어.

둘은 다른 질문이야. 게이트는 이 실행이 원본을 고쳤나를 물어. 가드는 이 세션이 그걸 읽었나를 물어. 차이가 보이면 그 깃발이 과부하 걸려 있다는 게 명백해져 — 과부하의 값은 파이프라인 셋이 자기네 제일 민감한 단계를 가드 하나 없이 위임 백 건 넘게 돌린 거였어. 다들 그 깃발이 덮어준다고 믿는 동안에.

이유를 따라가볼 값어치가 있어. 부주의가 아니거든. 그 파이프라인 중 하나엔 두 언어에 걸쳐 사실을 맞춰보는 게 통째로 자기 일인 늦은 단계가 있어. 그리고 맞춘다는 건 양쪽을 고친다는 뜻이야. 원본을 읽기만 하는 게 아니라 쓰는 거지. 그러니 그 파이프라인은 제한 깃발을 달 수가 없었어. 달았으면 계약이 요구하는 작업에 대해 쓰기 게이트가 실패했을 테니까. 그리고 그 깃발이 유일한 스위치였으니까, 원본을 진짜로 금지하는 그 파이프라인의 앞 단계는 가드를 하나도 못 물려받았고. 처방은 깃발을 뒤집는 게 아니라 깃발 하나한테 질문 둘을 그만 묻는 거였어.

실제 모양 둘, 그리고 왜 규칙 하나에서 둘 다 나오는지

깃발을 목록으로 바꿔. 어떤 단계가 어떤 입력을 닫는지. 그다음 첫 제한 단계부터 마지막까지 양끝 포함해서 가드를 세우면, 서로 다른 파이프라인 모양 둘이 저절로 나타나.

수리 파이프라인은 앞 단계를 제한하고 끝에서 원본을 열어. 봉인 구간이 앞쪽이지. 생성 파이프라인은 중간에서 원본을 집필하고 마지막 콜드 패스에서만 그걸 금지해. 구간이 뒤쪽이고. 같은 규칙, 반대 모양, 코드엔 특수 처리 없음.

양끝 포함인 이유는 맥락이 누적되기 때문

구간은 첫 제한 단계부터 마지막까지 이어져야 하고 그 사이 전부를 덮어야 해. 스스로는 아무것도 제한 안 하는 단계까지 다 들어가. 중간 단계에서 올라갔다가 다시 내려오는 봉인은 아무것도 안 지켜. 그 틈에 작업 맥락으로 들어온 게 제한 단계가 재개될 때도 여전히 거기 앉아 있으니까. 맥락은 단계 사이에 스스로 안 비워지고, 비워진다고 가정하는 설계는 화이트보드에서만 되는 설계야.

깃발 하나가 질문 둘에 답하고 있으면, 그 둘에 다르게 답하는 파이프라인이 조용히 가드를 잃는 쪽이야. 그 파이프라인을 먼저 찾아. 계약에 예외를 둔 쪽이고, 그 예외가 과부하를 안 보이게 만들거든. 전혀 다른 데서 뭔가 터지기 전까진 그래.

Code

규칙 하나, 모양 둘·python
REPAIR = {
    "required_stages": ["diag", "plan-gate", "fix", "reconcile"],
    # `reconcile` must open the source by contract, so the window
    # STOPS before it.
    "ko_only_stages": ["diag", "fix"],
}

CREATE = {
    "required_stages": ["sweep", "plan-gate", "compose",
                        "register", "ko-cold"],
    # `compose` AUTHORS the source, so the window starts after it.
    "ko_only_stages": ["ko-cold"],
}


def window(pipe):
    idx = [pipe["required_stages"].index(s)
           for s in pipe["ko_only_stages"]]
    return min(idx), max(idx)


# REPAIR  -> (0, 2)  a PREFIX: sealed from the start, opens at the end
# CREATE  -> (4, 4)  a SUFFIX: open until the end, then sealed
#
# Note REPAIR's window covers stage 1 (`plan-gate`), which restricts
# nothing itself. That is deliberate and it is the whole point:
# anything read during `plan-gate` is still in context at `fix`.


def armed(pipe, stages_logged):
    lo, hi = window(pipe)
    here = len(stages_logged)              # position, from the log
    return lo <= here <= hi


# Which makes stage logging LOAD-BEARING: the log is the only signal
# the guard gets about position. Skip an entry and the seal lags
# behind the run - and the direction of that failure DEPENDS ON THE
# SHAPE. For a PREFIX it over-seals: you are blocked from work you
# were entitled to do, which is loud and repairable. For a SUFFIX it
# UNDER-seals: `here` never reaches 4, the cold pass runs
# unguarded, and nothing says so. The suffix shape is the weaker seal
# for this reason too, not only because the author wrote the source.

External links

Exercise

네 시스템에서 소비자가 둘 이상인 불리언 깃발을 하나 찾아서, 소비자마다 실제로 뭘 묻고 있는지 적어봐. 질문이 같지 않으면 정답이 갈리는 경우를 찾아. 보통 딱 하나 있어. 그리고 그 경우가 지금 뭘 하는지 확인해. 그 경우는 깨져 있거나, 왜 괜찮은지 설명하는 주석을 달고 있거나 둘 중 하나고, 둘 다 알 값어치가 있어.
Hint
과부하된 깃발은 이름으로 제일 쉽게 잡혀. 특정 질문에 대한 답이 아니라 모드나 범주로 표현된 것들. 뭐인지로 이름 붙은 깃발은 표류하고, 뭐에 답하는지로 이름 붙은 깃발은 누가 알아채지 않고는 두 번째 소비자가 빌려 쓸 수가 없어.

Progress

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

댓글 0

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

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