要約

  • QUIC の各ストリーム方向は順序付きバイト列であり、STREAM フレームの境界はアプリケーションのメッセージ境界として保持されない。
  • FIN と RESET_STREAM は、消費したフロー制御クレジットを突き合わせるための不変な Final Size を伝える。
  • Final Size だけでは、アプリケーションが読み、解析し、コミットし、業務を完了したとは言えない。

運用画面が Final Size を見て要求を「完了」と表示することは珍しくない。しかし、その表示はトランスポートの事実とアプリケーションの結論を混ぜている可能性がある。ストリーム方向は、FIN を含む STREAM フレームで正常に終わることも、RESET_STREAM で途中終了することもある。どちらもバイトの会計上の終点を確定し得るが、アプリケーションがすべてを読んだか、処理したかは別問題である。

QUIC が示すのは、各方向の順序付きバイト列である。STREAM フレームの境界は、送信、再送、アプリケーションへの配送を通じて保存されない。メッセージの切り分けは上位のアプリケーションプロトコルが担う。したがって、フレーム境界を要求やトランザクションの区切りとして扱ってはならない。

FIN を持つ STREAM フレームでは、Final Size はフレームのオフセットとデータ長の合計になる。RESET_STREAM では Final Size フィールドが明示される。値は送信された最大バイトオフセットより一つ大きく、何も送信されなければゼロである。これはストリーム方向が消費したフロー制御クレジットを表す。接続レベルのフロー制御は、終了したストリームも含め、各ストリームの Final Size を合計する。ここで確定するのは資源の会計であり、業務上の成功ではない。

Final Size は一度確定すると変更できない。後から異なる値を示したり、その値以上の位置にデータを送ったりすれば、FINAL_SIZE_ERROR につながり得る。終了後も矛盾を検出するための状態を保持する場合がある。この不変性は会計の整合性を守るが、配送済みの証明に変わるわけではない。

受信には複数の状態がある。Final Size を知ることは、そこまでの全バイトを受け取ったことと同じではない。全バイトを受け取ることは、アプリケーションへ渡したことと同じではない。渡したことも、アプリケーションが読んだこと、解析したこと、永続化したこと、ロールバックや補償を実施したこと、業務を完了したこととは別である。RESET_STREAM は配送を中断し、未読データを破棄できるが、完全な未配送を証明しない。すべてのデータがすでにバッファに入っている可能性があり、reset の通知が抑制される場合もある。

パケット ACK はさらに下位の証拠である。STREAM フレームを処理するには、そのバイトをアプリケーション向けにキューへ入れる必要があるが、アプリケーションが読んだ、または使ったことまでは示さない。Final Size も、反対方向や接続全体の成功を示さない。

証拠台帳には、ストリーム ID と方向、FIN または RESET_STREAM、reset 時のアプリケーションエラーコード、Final Size の情報源と数値、観測した最大オフセット、連続して受信した範囲、全バイトが受信側に入ったか、アプリケーションへ渡ったか、読まれたか、メッセージのフレーミング、永続コミット、補償、ロールバック、業務結果、そして FINAL_SIZE_ERROR 検出のために保持した状態を別々に記録する。

五つの境界も維持しなければならない。TR-046 は送信前のフロー制御許可であり、最終会計ではない。TR-052 はメッセージ境界を持つ DATAGRAM を扱う。TR-053 は接続全体の CONNECTION_CLOSE を扱う。TR-054 は STOP_SENDING による停止要求と取消しを扱う。TR-045 は ACK が示すパケット処理の範囲を定める。いずれも Final Size やアプリケーション結果の代替ではない。