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

로그는 이빨이 없으면 삭아

~12 min · records, gates, design, process

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

선택 항목은 결국 다 비어

절차 문서만 요구하는 로그는 또 하나의 산문 규칙이고, 첫 트랙이 서술한 그대로 삭아. 누가 반대해서가 아니라, 결정하는 그 순간에 건너뛰는 비용이 0 이고 나중에 아무 데도 안 드러나서.

다들 본 적 있는 판은 손으로 유지하기로 돼 있던 메타데이터 필드가 지금 대부분의 레코드에서 몇 년째 낡아 있는 거야. 아무도 그만 갱신하기로 정한 적 없어. 그냥 한 번도 뭘 막은 적이 없어서, 사람들이 하는 일 집합에서 흘러나갔을 뿐이야.

이빨이 있다는 건 하류의 뭔가가 거기 의존한다는 뜻

처방은 사회적 의미의 단속이 아냐. 로그를 하중 받게 만드는 거야. 건너뛴 사람이 그 부재를 즉시 느끼도록 만드는 거지.

게이트가 로그를 읽고 구멍에서 실패해. 검증이 이 작업 단위에 대해 필수 단계마다 항목이 있는지 확인해. 불완전한 로그는 실패한 검증이고, 실패한 검증은 착지를 막아.

착지가 기록된 통과를 요구해. "착지 전에 검증하는 게 좋습니다"가 아냐. 착지 명령이 통과한 검증 이벤트를 찾고, 없으면 거부해. 무시 수단이 있고, 그 무시 자체가 기록돼. 가능하되 절대 실수로는 안 되는 것, 그게 맞는 모양이야.

가드가 거기서 자기 상태를 끌어와. 세 번째 트랙의 봉인은 어떤 단계가 기록됐는지를 읽어서 실행이 어디쯤인지 알아내. 항목을 건너뛰면 즉각적이고 눈에 보이는 결과가 따른다는 뜻이지.

셋의 공통점을 봐. 어느 것도 사람한테 기록하라고 부탁하지 않아. 기록이 있어야 다음 걸 할 수 있게 배치할 뿐이야. 규율에서 구조로 옮기는 그 수를, 이번엔 로그에 적용한 거고. 첫 트랙의 사다리로 말하면 로그를 1 칸에서 4 칸으로 올린 거지. 절차 문서에만 사는 기록은 권고니까.

이게 만드는 새 실수, 일부러 이름 붙이기

로그를 하중 받게 만들면 항목 쓰는 걸 잊었을 때 뭔가 깨져. 설계가 작동하는 거고, 동시에 전에는 없던 진짜로 새로운 틀리는 방법이야. 방향은 일부러 골랐어. 그 실패는 허용 안 된 작업을 허용하는 게 아니라 허용된 작업을 막고, 오류 메시지가 수리법을 말해줘.

다음 사람이 쫓기면서 발견하게 두느니 계약에 적어둘 값어치가 있어. 새 실패 양상이 문서화된 시스템이 남한테 넘길 수 있는 시스템이거든.

기록이 빠졌을 때 아무것도 안 깨지면 그 기록은 장식이고 일 년 안에 사라져. 그게 진짜로 필요한 하류 소비자를 하나 찾아서 의존을 걸어. 진짜 소비자 하나가 그 필드가 얼마나 중요한지에 대한 문서 아무리 많은 것보다 데이터 품질에 더 기여해.

Code

로그한테 이빨을 주는 게이트·python
def gate_stages_logged(delegation_id: int, pipeline: dict) -> tuple:
    """Every required stage has an entry against THIS unit of work.

    Note the filter: entries are matched on the delegation, not on
    the target. A stage logged against the target alone is invisible
    here - which produced a confusing failure where the CLI printed
    success and the gate reported the stage missing. The fix was to
    bind the entry to the session's own claim at write time.
    """
    logged = {e["stage"] for e in fetch_log(delegation_id=delegation_id)
              if e["event"] == "stage_done"}
    missing = [s for s in pipeline["required_stages"] if s not in logged]
    return (not missing, {"missing": missing})


def land(delegation_id: int, force: bool = False):
    """No green verification, no landing."""
    passed = [e for e in fetch_log(delegation_id=delegation_id)
              if e["event"] == "verified" and e["passed"]]
    if not passed and not force:
        raise SystemExit(
            "no passing verification logged on this unit of work - "
            "run it first (--force to override, which is on the record)")
    ...


# The override exists and is itself an event. "Possible but never
# accidental" is the shape to aim for: a guard with no override
# gets removed the first time it is wrong at 2am.

External links

Exercise

네 시스템에서 손으로 유지하기로 돼 있는 메타데이터 필드를 찾아서 얼마나 낡았는지 확인해. 그다음 그 운명을 정직하게 정해. 없으면 실패하는 진짜 하류 소비자를 하나 걸든가, 필드를 지우든가. 아무것도 의존 안 하는데 다들 채우라고 요구받는 필드는 둘 중 어느 쪽보다도 나빠. 주의력을 먹고 아무것도 안 돌려주니까.
Hint
걸기 제일 좋은 소비자는 그 필드를 채우는 사람이 자기도 돌리는 소비자야. 다른 팀이 느끼는 의존은 단속이고, 같은 사람이 몇 분 뒤에 느끼는 의존은 피드백이야. 그리고 피드백은 행동을 바꾸는데 단속은 반감이랑 우회로를 낳아.

Progress

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

댓글 0

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

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