実装

状態を扱ってみよう — 画面ではなく値を触れ

著者: makemind · 2026年1月23日

二週間前の番号板は 41 から動かなかった。ボタンが道具の名を呼ぶのに、その道具が無かった。

今回は付ける。ただ付ける前に決めなければならないことがひとつある — その数字を誰が持っているか。

なぜこれが問いなのか

画面が持っていればコードは短い。ボタンを押せば画面の中の値がひとつ上がり、画面が描き直される。サーバーは知らなくていい。

そして パネルをもう一台足したその日に終わる。 待合室の入口にひとつ、窓口の横にひとつ。それぞれ自分の数字を数えるので、二つが違う番号を出す。客は目の前のを見て、職員は横のを見る。

番号は画面のものではない。カウンターのものだ。

カウンターが持っている

だから状態はサーバー側にある。

var _now = 41;
var _issued = 41;

now は呼んでいる番号、issued は最後に発券した番号だ。

道具二つがこの二つを触る。

server.addTool(
  name: 'queue.next',
  description: 'Call the next number',
  inputSchema: const {'type': 'object', 'properties': {}},
  handler: (args) async {
    // The counter refuses to pass the last ticket it issued. Without this
    // the display runs ahead of the room and calls numbers nobody holds.
    if (_now >= _issued) return _state(notice: 'nobody is waiting');
    _now++;
    return _state(notice: 'called $_now');
  },
);

拒否から確かめる

付けてまず確かめたのは うまくいく場合ではなく、いってはいけない場合だった。

誰も待っていないのに「Call next」を押す。

pressed Call next -> now 41 ("nobody is waiting")
the counter refused: it will not call past the last ticket issued

41 から上がらなかった。 この検査が無ければ画面が部屋より先に進む — 誰も持っていない 42 を呼び、43 を呼び、本物の 42 を持った客が来たときにはもう通り過ぎている。

これで動く

券を三枚取る。

three tickets taken -> issued 44, 3 waiting
NOW SERVING 41 — 3 waiting · issued 44
NOW SERVING 41 — 3 waiting · issued 44

二回呼ぶ。

called twice -> now 43, 1 waiting
NOW SERVING 43 — 1 waiting · issued 44
NOW SERVING 43 — 1 waiting · issued 44

43 で、あと一人だ。 41 + 2 = 43、44 − 43 = 1。画面が計算したのではなく、カウンターが計算して送ってきた値だ。

画面側のコードには 41+1 も無い。{{now}}{{waiting}} の枠だけがある。

抜いて、挿す

ここがこの記事でいちばん重要な部分だ。

番号板は抜かれる。電源が落ち、パネルを替え、掃除でケーブルに触れる。そのとき何が起きるかは 確かめなければ分からない。

だから接続を切って別の表示装置を繋いだ。

display disconnected — the server process ends with it
a different display connects
it reads 43/44 before, 41/41 after
NOW SERVING 41 — 0 waiting · issued 41
NOW SERVING 41 — 0 waiting · issued 41

41 に戻った。 待ち人数も 0 だ。

これはバグではなく、このサンプルが実際にこう作られているという事実だ。状態が サーバープロセスのメモリにあり、表示装置を stdio で繋いだので、表示装置が死ねばサーバープロセスも一緒に死ぬ。キューがプロセスと一緒に消えた。

the number did NOT survive: this counter keeps its queue in memory,
so the process ending took the queue with it

このコンテンツは開発者以上が必要です

サインインしてプランをアップグレードすると続きを読めます。

プランを見る
Twitter