止まる場所をコードに埋め込む
目標
運用データを変更する前に止める場所を決め、その基準をコードに実際に執行させます。基準に引っかかったとき、半分だけ変わった状態が残らないところまで確認します。
依頼書
EAST地域のPENDING注文をCANCELLEDに変更してください。約120件です。
環境
/root/changeの下で作業します。現場は自分で作ります。準備であって、課題ではありません。
mkdir -p /root/change && cd /root/change
python3 - <<'PY'
import sqlite3, random, datetime
random.seed(23)
con = sqlite3.connect('app.db'); cur = con.cursor()
cur.execute("create table orders(id integer primary key, status text, region text, amount int, created_at text)")
base = datetime.datetime(2026, 8, 1); rows = []; oid = 1
for region, n in (('EAST', 480), ('WEST', 210), ('NORTH', 60), ('SOUTH', 35)):
for _ in range(n):
rows.append((oid, 'PENDING', region, random.randint(1000, 90000),
(base + datetime.timedelta(days=random.randint(0, 30))).isoformat())); oid += 1
for region in ('EAST', 'WEST', 'NORTH', 'SOUTH'):
for _ in range(random.randint(200, 400)):
rows.append((oid, random.choice(['PAID', 'SHIPPED']), region, random.randint(1000, 90000),
(base + datetime.timedelta(days=random.randint(0, 30))).isoformat())); oid += 1
cur.executemany("insert into orders values (?,?,?,?,?)", rows); con.commit(); con.close()
PY
sqlite3 app.db "select region, count(*) from orders where status='PENDING' group by 1"
作るもの
scope.txt 요청서 예상과 실제 대상의 차이
abort.md 중단 기준 (지표 · 임계값 · 행동)
restore.sh 스냅숏에서 되돌리는 스크립트
apply.sh 배치로 적용하되 기준에 걸리면 되돌리는 스크립트
split.md 되돌릴 수 없는 변경을 두 단계로 쪼개는 방법
stopped.md 멈췄다는 사실을 알리는 보고
apply.shは、依頼ファイルを1つ、引数として受け取ります。
region=EAST
expected=120
limit=0 0 이면 전부, 숫자면 그만큼만
採点方法
採点ツールが毎回、現場を元の状態に戻してからapply.shを3つの依頼で直接実行し、実行前後のDBを照合します。
region=WEST expected=150 limit=150 통과해야 한다 — 정확히 150건만 바뀐다
3つ目が重要です。止めるだけで仕事が進まないなら、それも失敗です。
ステップ
- 変更する前に数えます。実際の対象と依頼書の想定を、並べて書いてください。
abort.mdに中止基準を2つ以上書きます。それぞれに、観測するメトリクス・超えてはいけない値・そのときの行動の3つが揃っている必要があります。restore.sh: スナップショットのパスを受け取って元に戻します。採点ツールが意図的に壊したあと、このスクリプトで復旧するかを確認します。apply.shの範囲基準: 実際の対象が想定の2倍を超えたら、何も変更せず、0以外のコードで終了します。apply.shの不変条件の基準: どれかの地域のPENDINGが20件未満になったら、中止してすでに適用した分まで元に戻します。- 絞り込んだ条件では、ちょうどその件数だけが適用される必要があります。
split.md: 元に戻せない変更を、元に戻せる2段階に分けます。stopped.md: 止めた事実・理由・元に戻した範囲・再試行する条件。
参考
ステップ5が、このラボで最も難しいところです。バッチごとに確認しますが、引っかかったときにその場で止まってはいけません。半分だけ変わった状態は、どのドキュメントにもない状態なので、止めるというのは、たいてい元に戻すという意味です。ステップ3で作ったスナップショットが、ここで使われます。元に戻す手段を先に作らなければ、中止基準があっても、実行する手段がありません。
変更する前に数える
変更する前に数えます。実際の対象と依頼書の想定を、並べて書いてください。
依頼書は120件と言っていました。実際に何件かを先に数え、2つを並べて書いてください。この差を実行中に知ると、すでに手遅れです。
止める場所を紙に書く
abort.mdに中止基準を2つ以上書きます。それぞれに、観測するメトリクス・超えてはいけない値・そのときの行動の3つが揃っている必要があります。
1つの基準に、3つが全部必要です。観測するメトリクス、超えてはいけない値(不等号と数字)、そのときの行動です。3つのうち1つでも欠けると、実行中に解釈の余地が生まれ、解釈の余地はいつも続ける側に使われます。
元に戻す手段を先に作る
restore.sh: スナップショットのパスを受け取って元に戻します。採点ツールが意図的に壊したあと、このスクリプトで復旧するかを確認します。
スナップショットのパスを引数として受け取って、元に戻します。採点ツールがDBを意図的に壊したあと、このスクリプトで復旧するかを確認します。メッセージを出すだけで実際には元に戻さなければ、不合格になります。
範囲基準が実行を止める
apply.shの範囲基準: 実際の対象が想定の2倍を超えたら、何も変更せず、0以外のコードで終了します。
実際の対象が想定の2倍を超えたら、何も変更せず0以外のコードで終了します。採点ツールが実行前後のDBを照合するので、1件でも変わっていれば不合格です。
途中で引っかかったら元に戻す
apply.shの不変条件の基準: どれかの地域のPENDINGが20件未満になったら、中止してすでに適用した分まで元に戻します。
バッチごとに不変条件を確認し、引っかかったらステップ3のスナップショットで元に戻します。その場で止まってはいけません。半分だけ変わった状態は、どのドキュメントにもない状態です。
絞り込めば通らなければならない
絞り込んだ条件では、ちょうどその件数だけが適用される必要があります。
止めるだけで仕事が進まないなら、それも失敗です。limitを守ってちょうどその件数だけ適用し、下限も割り込んではいけません。
元に戻せないものを分ける
split.md: 元に戻せない変更を、元に戻せる2段階に分けます。
最もよい中止基準は、元に戻せない変更をそもそも作らないことです。削除の代わりに削除マークを残し、猶予期間のあとで消せば、元に戻せない1回が、元に戻せる2回になります。
止めたという事実も報告の対象である
stopped.md: 止めた事実・理由・元に戻した範囲・再試行する条件。
元に戻したから何もなかったことにして済ませると、顧客企業はあとでログから痕跡を見つけ、隠したと受け取ります。止めた事実・理由・元に戻した範囲・再試行する条件の4つで、1サイクルです。