二週間前の番号板は 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

二回呼ぶ。
called twice -> now 43, 1 waiting

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

41 に戻った。 待ち人数も 0 だ。
これはバグではなく、このサンプルが実際にこう作られているという事実だ。状態が サーバープロセスのメモリにあり、表示装置を stdio で繋いだので、表示装置が死ねばサーバープロセスも一緒に死ぬ。キューがプロセスと一緒に消えた。
the number did NOT survive: this counter keeps its queue in memory,
so the process ending took the queue with it