テレビのアニメはどこから来る? / 第11話

第11話:イトは、最後の一席を手放した|APIが画面を変えるまで

ピコルート第11話。アニメ最終話の上映まで三分、イトの画面には残り1席、APIの返事には残り0席。古い表示を信じるか、最後の席を手放して現在のデータへ直すかを選びます。

API追加データリクエストレスポンス10分更新

最後の一席が、イトの画面で青く光っていた。

最終話上映 残り1席

上映まで、あと三分。

ピコルート・ラボの小さな上映室には、椅子が十二脚しかない。

イトは12番席の仮札を持っていた。受付を手伝い終えたら、ずっと待っていたアニメの最終話を、その席で見るつもりだった。

「間に合った」

イトは予約ボタンへ指を置く。

その瞬間、画面の端で細い光が走った。

別の場所から届いた予約が、先に12番席へ入った。

けれど、イトの画面はまだ「残り1席」のままだ。

イト

僕の画面では、まだ一席あるよ

ユイ

その表示は、ページを開いた時の数かもしれません

ピコ

今の席を確かめるお願いを、API受付へ送ってみよう

上映まで、あと二分四十五秒。

開いたページの数字は、古くなる

イトがページを開いたとき、残席は確かに1だった。

その数字は、最初に届いたHTMLと一緒に画面へ置かれている。

しかし、ページを開いた後も、ほかの人の予約は動く。

誰かが最後の席を取っても、イトの手元にある古い数字が自分で0へ変わるわけではない。

画面の見た目と、予約側が持つ現在の状態が離れた。

イトが予約ボタンを押す。

JavaScript操作室から、小さなrequestが飛び出した。

{
  "screeningId": "finale",
  "seatId": 12
}

requestは、映画一覧でもニュース一覧でもない。12番席を予約するための窓口へ向かう。

APIは、アプリやサービスが決まった窓口へrequestを送り、dataや機能のresponseを受け取るための接点だ。

どの窓口に何を頼めるかは同じではない。OpenAPI Specificationのような記述形式では、HTTP APIのoperation、parameter、request body、possible responsesを、人とcomputerが理解できる形で表せる。

ただし、すべてのAPIがOpenAPIを使うわけではない。ここで大切なのは、お願い先と頼み方がAPIごとの約束で決まることだ。

返事は、完成した画面ではなかった

光の道からresponseが戻った。

中に、上映ページは入っていない。

入っていたのは、短いdataだった。

{
  "reserved": false,
  "remaining": 0,
  "reason": "already_taken"
}

JSONは、nameとvalue、object、arrayなどを使ってstructured dataを表せるtext formatだ。RFC 8259に基本の表現規則がある。

APIのresponseがJSONとは限らない。画像、text、file、空のbodyなど、別の返し方もある。

今回のresponseが伝えたことは三つだ。

イトの予約は成立していない 現在の残席は0 12番席は先に取られた

イトの画面では、青い「残り1席」がまだ点灯している。

response cardには、赤い「残り0席」がある。

上映まで、あと一分五十九秒。

うまくいかなかった返事も、現在のdata

「エラーなら、もう一回押せば取れるかも」

イトが予約ボタンへ戻ろうとする。

マコトが、二枚の札を並べた。

古い画面には1。

APIの現在の返事には0。

マコト

同じrequestを急いで繰り返す前に、なぜ成立しなかったかを見よう

ピコ

今の状態とぶつかって完了できないrequestには、conflictを示す返し方もあるよ

ユイ

失敗のresponseも、利用者へ次の行動を伝えるdataなんですね

HTTPの409 Conflictは、requestが対象resourceの現在状態と衝突して完了できない場合に使える。RFC 9110では、利用者が衝突の原因を認識できる情報をresponse contentへ含めることが望まれている。

この上映室APIはフィクションで、競合時に409を使う一つの設計例だ。実際の予約serviceがすべて同じstatusやdataを返すわけではない。

赤いresponseは、イトを困らせるための札ではなかった。

古い1席をもう誰かが取ったという、現在の状態を知らせている。

イトが選べる三つの道

ピコが、三枚の札を机へ置いた。

  1. 古い席を取る
  2. 返事を隠す
  3. ゼロへ直す

一枚目なら、手元の「残り1席」を根拠に12番へ座れる。けれど、同じ席を予約した人と重なる。

二枚目なら、赤いresponseを画面から消せる。けれど、次にページを見る人にも古い1が残る。

三枚目なら、現在のresponseをJavaScriptへ渡し、残席だけを0へ直す。ページ全体を閉じる必要はない。

イトは、手にある12番席の仮札を見た。

上映まで、あと一分二十一秒。

仮札を折り、受付の未成立箱へ入れた。

「ゼロへ直す」

イトはresponse cardを、残席counterへ差し込んだ。

青い1が消える。

赤い0が点灯する。

イトが最後の席の仮札を自分の手で折り、別の予約札がついた座席を背に、残席表示が空席なしへ変わるのを受け入れている
古い一席を押し通さず、自分の仮札を折って、現在の返事を残席表示へ反映する。

予約ボタンは、「満席」に変わった。

12番席の背には、別の場所から届いた青い予約札がついた。

二重予約は起きなかった。

ページ全部ではなく、残席だけが変わった

上映作品の絵。

開始時刻。

上映室の案内。

ページのほかの部分は、そのまま残っている。

変わったのは、残席counterと予約ボタンだけだ。

Fetch Standardは、Web platformにおけるrequest、response、それらを結ぶfetching processを定めている。JavaScriptはこうした仕組みを使ってdataを取りに行き、届いた値を必要な画面部品へ反映できる。

これは「APIを使えば常にreloadしない」という意味ではない。serviceの作り方や操作によって、ページ遷移や全体reloadが起きることもある。

今回、イトの画面で起きた順番は短い。

予約ボタンを押す JavaScriptがAPIへrequestを送る APIが現在のresponseを返す JavaScriptが残席counterを1から0へ変える

最初に見えていた1は、嘘ではなかった。

ただ、今の数字ではなくなった。

イトの席は、画面からも消えた

上映開始の音が鳴った。

12番席には、予約した人が座った。

イトの仮札は、未成立箱の中にある。

「映写操作、僕がやる」

イトは客席の後ろにある小さな操作室へ入った。

映像を送るmonitorは見える。

けれど、客席の大きなscreenは、イトの背中側だ。

最終話が始まると、操作室の窓にだけ青い光が反射した。

壁の残席counterは0のまま。

途中で1へ戻ることはなかった。

イトは、破棄した仮札と赤いresponse cardを操作卓の横へ置いた。

古い表示と現在の返事が違うとき、自分に都合のよい古い数字へ画面を戻さない。

上映室から笑い声が聞こえた。

イトは振り返らず、次の映像を送るleverへ手を置いた。

次回:返事を作るサーバーはどこにいる?

上映が終わり、イトは最後のresponse cardを裏返した。

そこには、席のdataを返した窓口の先へ続く道がある。

「この0は、誰がどこで数えて返したんだろう」

ピコが、API受付の奥へ続く重い扉を示した。

次回、ピコルート第12話。

返事を用意するサーバーは、どこで待っている?

画面のむこう側をもっと知る

物語で見たrequest、response、endpoint、JSONを用語として整理するなら、APIとはで図と一緒に確かめられます。

この物語を、解説で深める

第11話で生まれた疑問を、解説記事で少し深く見ていきます。物語で感じた不思議さを残したまま、言葉と仕組みを順番に整理しましょう。

APIとは|アプリやサービスがデータをやり取りする窓口を読む