フィールド制約と値の範囲
リクエストフィールド (C→S)
| フィールド | 型 | 有効範囲 | 意味 | 違反時 |
|---|---|---|---|---|
op | ASCII 1B | A(0x41) · R(0x52) | リクエストの種類 | E bad_op |
wait | u8 | 0〜255(秒) | 0はキューに入らない即時試行、1..255は獲得待機の上限 | —(型として常に有効) |
lease | u8 | 1〜250(秒) | リース。0と251..255は拒否/reserved | E bad_lease |
owner | u64 BE | 0 〜 2^64-1 の全域 | 獲得試行の識別子 (クライアントが生成) | — (サーバーは検査しない) |
token | u64 BE | サーバーが発行した値 | 解放対象の指定 (R専用) | 不一致なら N |
key | UTF-8 | 1 〜 128 バイト | ロック名。空白(0x20)・改行(0x0A)は不可 | E bad_key |
- 無限のwait/leaseはありません。公式クライアントは秒未満を切り上げて範囲を検証し、範囲外の値をclampせず送信前に明示的な入力エラーを返します。デフォルトleaseは30秒です。
- 公式client APIの
waitは、呼び出し開始からlocal queue、送信が確実に行われていない接続再試行、write、応答までを含むacquire全体の上限です。monotonic operation deadlineは一度だけ作成し、writerは実際の送信直前に残り時間をu8秒へ切り上げてframeのwaitへ入れます。そのため接続の復旧が遅れたり、確実な未送信failoverが起きてもserver waitが最初から始まり直すことはありません。deadline時にまだqueue内なら確実な未送信timeout、1 byteでも送信された可能性があれば該当する正確なsessionを閉じてIndeterminateとします。元のwait=0だけがwire0を使い、この即時試行にも停止したtransportを無期限に待たない別の有限I/O deadlineがあります。ただしdeadline直前に相関済みのAをTicket配信gateで遅れて確認した場合、server waiterはすでに解消済みなのでsessionは閉じず、既知のexact tokenを補償releaseしてIndeterminateで終了します。相関済みのT/Bは確定した未獲得です。 - 元の
wait=0はwireでもserver側でもqueueに入らない1回の即時試行のままです。別の5秒transport deadline内では、確実に未送信の場合に限り同じownerで接続を選び直してretryできます。1 byteでも送信された可能性が生じた後はacquireを再送しません。 - 公式クライアントAPIではwireに存在しない
min_work_budgetが必須です。critical work + 想定pause + DB commit/rollback完了を含む0..250秒で、正規化後のlease以下でなければなりません。違反は送信前にUnsupportedDuration/InsufficientLease系エラーになります。 - キーの長さは文字数ではなくバイト数です — 日本語はUTF-8で1文字あたり3バイトなので、 最大42文字です。
ownerは応答相関IDにすぎず、権限ではありません。同じ値を再利用してもactive tokenの返却やlease更新は行いません。同一クライアントの同時in-flight要求では曖昧さを避けるため異なる非0値が必要で、公式クライアントはcounterが0またはwrapするとfail-closedします。- explicit releaseと既知tokenの補償releaseは、call/enqueue時点から再接続・再試行を含めて絶対5秒です。
Rは成功、Nは既に消失または現在tokenではないことを示します。応答未確認を成功と推定せず、bounded補償queueが満杯ならlease expiryに委ねます。 bad_keyは、空のキー、128バイトを超えるキー、空白や改行を含むキー、不正なUTF-8を すべて同様にカバーします。公式クライアントはさらに\rを決して送信しません —\rで 終わるキーは気づかないうちに別のキーになってしまうためです。
レスポンスフィールド (S→C)
| フィールド | 型 | 範囲 | 現れるレスポンス |
|---|---|---|---|
token | u64 BE | 1以上、発行のたびに増加 | A(新規発行) · R/N(リクエストのエコー) |
owner | u64 BE | リクエストの値そのまま | A · T · B (リクエストのエコー) |
key | UTF-8 | リクエストの値そのまま (1〜128B) | A · T · B · R · N |
addr | UTF-8 | host:port | M · L |
reason | ASCII | 定められた8種類 | E |
サーバーはtoken 0を発行しません。singleは現在のprocess lifetime内のcounter、clusterは合意で複製されたcounterを使い、overflow前にfail-closedします。wall clockや乱数による再起動後の単調性は保証しません。
固定ヘッダー長
op以降に続く固定長のバイナリ区間です。これらのバイトは0x0Aを含む可能性があるため、 パーサーは改行を探す前にこの長さだけ先に消費しなければなりません。
| 方向 | op | 固定ヘッダー | 構成 |
|---|---|---|---|
| C→S | A | 10 B | wait(1) + lease(1) + owner(8) |
| C→S | R | 8 B | token(8) |
| S→C | A | 16 B | token(8) + owner(8) |
| S→C | T · B | 8 B | owner(8) |
| S→C | R · N | 8 B | token(8) |
| S→C | M · L · E | 0 B | なし (op直後からテキスト) |
バイトが足りなければE bad_requestです。
フレームサイズ
| 項目 | 値 |
|---|---|
フレーム上限 (\nを除く) | 192 バイト — 超過時は E line_too_long |
最大のAリクエスト | 1 + 10 + 128 + 1 = 140 B |
最大のRリクエスト | 1 + 8 + 128 + 1 = 138 B |
最大のAレスポンス | 1 + 16 + 128 + 1 = 146 B |
空フレーム (\nのみ) | keep-alive — サーバーが無視 |
192B上限は最大frame(146B)より十分大きいため、仕様準拠clientは到達しません。構造不正またはoversized frameの後はframingを信頼せず、接続を閉じます。
認証ハンドシェイク
| 項目 | 値 |
|---|---|
| ハッシュ | SHA-256 (challenge行に明記) |
| nonce | base64url文字8文字 |
| レスポンスダイジェスト | base64url43文字 (パディングなし) |
| 行の上限 | 256 バイト |
| 制限時間 | 10秒 (TLSネゴシエーションを含む) — 超過時は接続を閉じる |
詳しい手順は認証ハンドシェイクを参照してください。
サーバー側の上限
クライアントが直接設定しませんが、動作に影響する値です。
| 項目 | デフォルト | 設定 | 超過時 |
|---|---|---|---|
| keyごとのwaiter | 2048(hard cap 16384) | MAX_WAITERS | B(busy) |
| 全waiter | 16384(hard cap 65536) | MAX_TOTAL_WAITERS | 該当acquireにB |
| 同時client接続 | 1024(hard cap 8192) | MAX_CONNECTIONS | 接続を即時close |
| 接続ごとの未送信reply | 256 | compile-time | 遅いclient接続をclose |
| 全in-flight acquire | 4096 | compile-time | 該当acquireにB |
| 全in-flight release | 512、別lane | compile-time | 接続終了までbounded待機 |
| cluster active key | 65536 | compile-time | 新規key acquireにB |
read buffer(4096B)、reply batch(64)、開始済みclient frameのprogress timeout(5秒)、single expiry sweep(5秒)はcompile-time定数です。cluster expiryは全scanではなくtoken検証付きdeadline min-heapを使います。全設定は設定(環境変数)を参照してください。
全acquire・新規key・全waiterのadmissionはhard limitの90%で閉じ、使用量が75%未満になってから再開します。 そのためhard limit前でも新規acquireはBになり、releaseとRaft recoveryの予約capacityは別枠です。
違反 → レスポンス早見表
| 状況 | レスポンス | 接続 |
|---|---|---|
| 未知のop | E bad_op | 閉じる |
| 固定ヘッダー不足 | E bad_request | 閉じる |
lease = 0または251..255 | E bad_lease | 閉じる |
| キーが空 / 128B超過 / 空白・改行を含む / UTF-8でない | E bad_key | 閉じる |
| フレームが192B超過 | E line_too_long | 閉じる |
| 認証ダイジェスト不一致 | E auth_failed | 閉じる |
| 待機キューが飽和 | B + owner + key | 維持 |
| 解放トークン不一致 | N + token + key | 維持 |
すべてのエラー理由と接続の扱いは レスポンス · エラー Eを参照してください。