식당 문 앞에 태블릿이 한 대 있고, 카운터 안쪽에 한 대가 더 있다. 둘은 같은 줄을 본다.
이게 생각보다 어렵다. 문 앞 사람은 손님을 적고, 카운터 사람은 다음 팀을 부른다. 두 화면이 각자 "지금 네 팀"이라고 기억하기 시작하면, 카운터가 한 팀을 앉힌 순간 문 앞은 여전히 네 팀이다. 그리고 그 어긋남은 손님과의 말싸움으로 나타난다. 대기 관리 도구를 월 구독으로 파는 회사들이 파는 것의 상당 부분이 사실 이 어긋남을 안 나게 하는 일이다.
서버 하나에 화면 두 장으로 그걸 만들었다.
문 앞

큰 숫자 하나, 예상 시간 하나, 목록. 문 앞 화면이 하는 일은 그게 전부다.
목록의 "next", "1 ahead", "2 ahead" 는 저장돼 있지 않다. 줄에서 몇 번째인지는 목록의 순서에서 나온다.
// Position is derived from the list order. Nothing stores
// "you are third" — that would be wrong the moment somebody
// ahead gives up and leaves.
'ahead': i == 0 ? 'next' : '$i ahead',
앞 팀이 기다리다 가버리면 뒤 팀은 자동으로 한 칸 당겨진다. 저장했다면 누군가 전부 다시 써야 한다.
카운터

#41 Han (2). 버튼도 그 팀 이름을 안고 있다카운터 화면은 같은 줄을 다르게 본다. 손님에게 보여줄 게 아니니까 각 팀이 얼마나 기다렸는지가 붙는다.
counter sees the same 4 parties, front of the line has waited 20 min
the same 4 parties — 이 줄이 이 글의 절반이다. 두 화면이 각각 서버에 물어봤고 같은 답을 받았다.
부른다
카운터에서 버튼을 누르면 맨 앞 팀이 앉는다.

#42 Oduya (4) 로 넘어갔고 THIS SHIFT 에 착석 1 · 평균 대기 20 min · 현재 안내 27 min 이 찍힌다여기서 두 가지가 동시에 일어난다. 목록에서는 빠지고, 기록에는 남는다.
// The party leaves the waiting list but not the record. An owner who
// wants to know how long people actually waited has to be able to ask
// afterwards, and a deleted row cannot answer.
p.calledAtNote = 'waited ${_now - p.joinedAtMinute} min';
_served.add(p);
화면 아래 seated today: 1 — Han waited 20 min 이 그 기록이다. 사장이 "우리 집 평균 대기가 얼마냐"고 묻는 순간 필요한 게 이것이고, 지운 행은 대답하지 못한다.
그리고 아무도 손대지 않은 문 앞

이 화면은 아무도 건드리지 않았다. 카운터에서 버튼 한 번 눌렀을 뿐이다.
door reads: 4 parties, 11 people, about 36 min
counter called: called Han (41) — Han waited 20 min
door now reads: 3 parties, about 27 min — nobody edited this screen
estimate 36 min -> 27 min because the list is 4 -> 3
36분이 27분이 된 건 누가 27을 써 넣어서가 아니다. 목록이 넷에서 셋이 됐고, 예상 시간은 목록에서 계산되기 때문이다.
// The estimate the person at the door reads out loud.
'estimate': '${_waiting.length * _minutesPerTable} min',
_minutesPerTable 은 9다. 사장이 평생 한 번 바꿀까 말까 한 숫자고, 그래서 그 숫자만 한 곳에 있다.