在门外的队结尾我们写过这样一段。
没有推送。 柜台一叫、门口跟着变,这是真的,但那是因为测试装置把同一份状态塞进了两个运行时。这个样例没有做那件事。
这一篇来做。
拿在手上的画面和挂在墙上的画面
到目前为止的样例全都是靠问才知道的。画面调用工具、拿到答案、画出来。
拿在手上的画面可以这样。人按下去的那一刻,就是该问的那一刻。
钉在墙上的画面不一样。 没有人会去按后厨的显示屏。于是它只会变成两者之一。
- 不停地问 — 每秒问一次,一天就是 8 万 6 千次。其中有意义的答案不过几百次
- 变晚 — 每 10 秒问一次,订单最多会晚 10 秒才出现
两个选项都糟,而第二个尤其糟。 在后厨,10 秒很长。
把队列做成资源,而不是工具的返回值
server.addResource(
uri: _queueUri,
name: 'Kitchen queue',
description: 'Tickets the kitchen still has to make',
mimeType: 'application/json',
handler: (uri, params) async => ReadResourceResult(...),
);
而队列一动,服务器就说话。
_tickets.add(_Ticket(_next++, _incoming[i++]));
// The whole point. Nobody asked; the server says the queue moved.
server.notifyResourceUpdated(_queueUri);
画面这一侧订阅一次就完事。
client.onResourceUpdated((uri) async { ... });
await client.subscribeResource(_queueUri);
调用次数就是证据
这类主张用嘴是验证不了的。写着「用的是推送」而背地里在轮询的代码很常见。
所以测试装置去数自己调用了多少工具。
subscribed to orders://queue — from here the screen asks for nothing
--- window opens: tool calls so far 1 ---
told: orders://queue changed (notification 1)
told: orders://queue changed (notification 2)
told: orders://queue changed (notification 3)
--- window closes ---
notifications received: 3
screen updates: 3
tool calls made by the screen inside the window: 0
0。 三单送达期间,画面什么都没问。

验证守住这个 0。
grep -q "tool calls made by the screen inside the window: 0" captures/run.log \
|| { echo " the screen asked for something — this is polling, not push"; exit 1; }
而且画面定义里也不能有轮询。
if grep -RIqiE '"(poll|interval|refresh|timer)"' kitchen.mbd; then
echo " the screen definition is polling"; exit 1
fi