同時に書いても、壊れない

シリーズ・第 5 回 — 「AI エージェントのためのタスク管理をつくる」。前回は活動範囲を構造で区切る話でした。今回は、同じファイルを同時に触る話です。

第 2 回で、Amenbohttps://amenbo.work/)の CLI と GUI が同じ store.sqlite を触ると見ました。別々のプロセスが、1つのファイルを同時に書く。普通なら壊れそうです。なぜ壊れないのかが、今回の話です。

書き込みは、丸ごと1トランザクション

コツは2つあります。

1つは、各書き込みを丸ごと1つのトランザクションにまとめること。SQLite は書き込みを直列化するので、2つのプロセスが同時に来たら、片方が待ちます(最大 5 秒)。取り合って失敗するのではなく、順番に通る。

もう1つは、途中で失敗したら、丸ごと巻き戻すこと。なぜ「丸ごと」が要るのか。以前、書き込みを1件ずつ流していた頃は、混み合った瞬間に半端な行が残ることがありました。書きかけの行が空のまま残ると、その1行のせいでストア全体の読み取りが止まる。1つのトランザクションにまとめてからは、失敗しても何も残りません。

並行書き込みの安全性。CLI と GUI の2つのプロセスが、同じ store.sqlite(WAL・単一ファイル)に書き込む。各書き込みは丸ごと1トランザクションで、SQLite が直列化する。同時なら片方は待つ(busy_timeout 5秒)。途中で失敗しても丸ごと巻き戻るので、半端な行(torn write)は残らない。
各書き込みは丸ごと1トランザクション。同時なら片方が待ち、失敗すれば巻き戻る

変更は、change_feed で伝わる

CLI で書いた内容が、GUI にすぐ映る。これはどうやっているのか。

書き込みのたびに、同じトランザクションの中で、「何が変わったか」を change_feed という小さな記録に 1 行残します。値は持たず、どのレコードが変わったかだけ。GUI はファイルの変化を見張っていて、change_feed の続きをたどり、変わったぶんだけ読み直します。関係する画面だけが更新され、全部を読み直すことはありません。

だから、CLI や AI がターミナルから書いても、GUI はほぼ即座に、必要なところだけ追いつきます。

変更が伝わる流れ。CLI が書き込むと、同じトランザクション内で change_feed に「何が変わったか」を1行残す。GUI のウォッチャがそれに気づき、カーソルで変わったぶんだけ読み直して、その画面だけを更新する。全部を読み直さない。
変更は change_feed に1行。GUI はそれをたどって、変わった画面だけ更新する

次回

第 6 回:AI のセッションを、並行で回す です。今回は1つのファイルを同時に触る話でしたが、次は AI のセッションそのものを2〜3本並べて開発を回す話 —— git の worktree と、todo からしか通らない予約の使い方を、実際の事例として書きます。

☕ チップを送る