Bencher Runner プロトコル


runner バイナリ と API サーバーは、単一の WebSocket 接続を通じて 通信します。このリファレンスでは、そのプロトコル、すなわちやり取りされるメッセージ、それらが 駆動する Job のライフサイクル、そしてタイムアウトと再接続によって Job が停止しないように する仕組みについて説明します。これは セルフホスト型 Runner ガイドの詳細な補足です。

runner up で Runner を運用するためにこれらを知る必要はありません。 これは透明性のため、また API の周辺でツールを構築する人のために提供されています。


接続

Runner はそのライフサイクル全体を通じて、API サーバーへの単一の WebSocket 接続を維持します。 同じ接続が Job の割り当てと Job の実行の両方を処理し、 多数の Job にわたって開いたままになるため、Job ごとの再接続とハンドシェイクを回避します。

  • エンドポイント: /v0/runners/{runner}/channel
  • 認証: 接続が確立される際に、Runner キーが Authorization: Bearer bencher_runner_<key> ヘッダーとして送信されます。
  • メッセージサイズ: 各メッセージは、サーバーの request_body_max_bytes 制限によって上限が定められます (最大メッセージサイズとフレームサイズの両方に適用されます)。大きな stdoutstderr、または出力ファイルを運ぶ completed ペイロードのように、この制限を超えるメッセージは、WebSocket プロトコルレベルで拒否されます。

すべてのメッセージは、その種類を識別する event フィールドを持つ JSON オブジェクトです。


Runner メッセージ

Runner からサーバーに送信されるメッセージ。

イベント説明ペイロード
readyRunner はアイドル状態で Job を要求しているオプションの poll_timeout (1〜900 秒) と runner メタデータ (osarchversion)
runningJob のセットアップが完了し、ベンチマークが開始するなし
heartbeat定期的な生存シグナル (約 1 秒に 1 回)なし
completedベンチマークが正常に完了したjob (Job UUID) と results (反復ごとの出力)
failedベンチマークが失敗したjob (Job UUID)、resultserror
canceledサーバーからのキャンセルを確認応答するjob (Job UUID)

サーバーメッセージ

サーバーから Runner に送信されるメッセージ。

イベント説明ペイロード
ack受信したメッセージを確認応答するオプションの job (Job UUID)
job要求された Job を Runner に割り当てる要求された Job: その Spec、Job 設定、そして短命の OCI プルトークン
no_jobポーリングタイムアウトが切れ、利用可能な Job がなかったなし
cancelJob がキャンセルされたかタイムアウトした。実行を停止するなし
updateRunner は新しいバージョンへ自己更新すべきversionurl (ダウンロード URL)、checksum (SHA-256)

job メッセージ内の OCI プルトークンは、Job が要求された際に生成され、保存されることはありません。 これは Job が属する単一のプロジェクトにスコープが限定され、プル専用かつ短命であるため、 侵害された Runner は、自身が要求した Job のプロジェクトの Image しかプルできません。


接続フロー

接続後、Runner はアイドルのポーリングループに入り、 サーバーが job を割り当てる (またはポーリングがタイムアウトすると no_job を、新しいバージョンが利用可能になると update を返す) まで ready を送信し続けます。 Job を取得すると、Runner は running を送信し、 ベンチマークの実行中は heartbeat メッセージをストリーミングし、 最終的に終端メッセージである completed または failed で終了します。 サーバーは各メッセージを ack で確認応答し、 接続は開いたままになるため、Runner は次の Job のためにアイドルループへ戻ります。

Job がキャンセルされると、サーバーは heartbeat に対して cancel で応答します。 Runner はベンチマークを停止して canceled で応答し、サーバーはそれを確認応答します。

API ServerRunnerAPI ServerRunneralt[Job available][Poll timeout][Update available]loop[Idle / polling]loop[Benchmark executes]Connect with runner keyConnectedready (os, arch, version)job (Spec, config, OCI token)no_jobupdate (version, url, checksum)runningackheartbeatack (or cancel)completed (job, results)ack

Job のライフサイクル

各 Job は、要求、実行、処理される過程で、決まった一連の状態を遷移します。

遷移元遷移先トリガー
pendingclaimedRunner が Job を要求する
pendingcanceledユーザーが Job をキャンセルする
claimedrunningRunner が running を送信する
claimedfailedRunner が failed を送信する、またはハートビートがタイムアウトする
claimedcanceledユーザーが Job をキャンセルする
runningcompletedRunner が completed を送信する
runningfailedRunner が failed を送信する、またはハートビートがタイムアウトする
runningcanceledユーザーが Job をキャンセルする、またはハードな Job タイムアウトを超過する
completedprocessedサーバーが結果を正常に処理する
failedcompletedRunner が completed を再送し、ハートビートタイムアウトによる失敗を上書きする

processedcanceled は終端状態です。 completedfailed は準終端状態です。 completed は結果が解析されると processed に遷移し、 failed は Runner が completed を再送すると completed に遷移します。 すべての遷移は、データベース更新時にステータスフィルターを使用するため、 並行して変更された Job は上書きされるのではなく、再読み込みされます。

runner claims

user cancels

running

failed / timeout

user cancels

completed

failed / timeout

cancel / hard timeout

results recovered

results parsed

pending

claimed

canceled

running

failed

completed

processed


タイムアウトと回復

Runner がクラッシュしたり接続を失ったりした場合でも、 Job が決して停止しないようにする 3 つの補完的な仕組みがあります。

ハートビートタイムアウト

接続が開いている間、読み取りタイムアウトが、接続されているが応答のない Runner を検出します。 有効なプロトコルメッセージのみがタイマーをリセットします。 無効な JSON、ping/pong フレーム、バイナリメッセージはリセットしません。 タイムアウト時、自身のタイムアウトに猶予期間を加えた時間を超えて実行された Job は canceled とマークされ、 そうでない場合は failed とマークされます (Runner との接続が失われたため)。

ハードな Job タイムアウト

サーバーは Runner の挙動とは独立して、ハードな最大実行時間を強制します。 これにより、バグのある、または侵害された Runner が、ハートビートを送信し続けて無期限に実行することはできません。 制限 (Job のタイムアウトに猶予期間を加えた時間) を超えると、 Job は canceled とマークされ、Runner は cancel メッセージを受信します。

切断からの回復

Job がまだ進行中に接続が切断された場合、 サーバーはハートビートタイムアウト後にチェックをスケジュールします。 Runner が再接続してハートビートを再開していれば、Job は継続されます。 そうでない場合、Job は failed とマークされるか、ハードタイムアウトを超過していた場合は canceled とマークされます。 起動時には、サーバーは孤立した claimed の Job も回復し、 進行中の Job のタイムアウトを再スケジュールし、 結果は保存されたがまだ解析されていない completed の Job を再処理します。

再接続と結果の配信

再接続はサポートされており、冪等です。 すでに実行中の Job に対して running を再送しても、その生存状態が更新されるだけであり、 終端メッセージである completedfailedcanceled の再送は常に安全です。 終端メッセージは Job UUID を運び、ack を受け取ります。 ack が届く前に接続が切断された場合、 Runner は結果を保存し、次の接続でアイドルに戻る前にそれを再送します。 Runner の実際の completed 結果は、ハートビートタイムアウトによる failed ステータスを上書きすることさえできます。

自動リトライなし

failed の Job は自動的にリトライされません。 失敗したベンチマークは隠すべきエラーではなくシグナルであるため、 再実行はあなたに委ねられています。


Job の出力

Runner が completed または failed を送信すると、 完全な出力は、コンテナ Image に使用されるのと同じ OCI ストレージバックエンドの {project}/output/v0/jobs/{job} というパスに保存されます。

保存された出力には、反復ごとの results 配列と、失敗時には error 文字列が含まれます。 各反復は、その exit_codestdoutstderr、 そして収集された出力ファイルとその内容のマップを記録します。 出力が保存された後、サーバーは結果に対して ベンチマークハーネスアダプター を実行し、 Metric と Alert を解析して Report に取り込み、Job を processed へ遷移させます。

出力は、GET /v0/projects/{project}/jobs/{job} API で Job を照会したときに返されます。 WebSocket メッセージの上限を定めるのと同じ request_body_max_bytes 制限が、 Runner が配信できる出力のサイズを制限します。



Published: Fri, June 19, 2026 at 8:00:00 AM UTC