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、オプションの更新 channel、オプションのバイナリ checksum)
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 しかプルできません。

stable 更新チャネルでは、Runner のバージョンがサーバーのバージョンと異なる場合に update が送信されます。 canary 更新チャネルでは、versioncanary となり、 Runner が自己申告したバイナリのチェックサムが 公開されているローリング canary ビルドと異なる場合に update が送信されます。


接続フロー

接続後、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 | Last Updated: Tue, July 7, 2026 at 8:00:00 AM UTC