8分

プロキシを迂回せずに大容量ファイルをアップロードする

OpenMakeが巨大な単一リクエストをユーザー単位のチャンクプロトコルへ変更し、既存のエージェントタスク用ファイル契約を維持した過程を解説します。

  • エージェントタスク
  • セルフホスト
  • アップロード
  • Cloudflare
実行中と完了済みのタスクを表示するOpenMakeのエージェントタスク画面
ユーザーが見るエージェントタスクの流れは変えず、大きなバイナリ添付の転送方式だけを変更しました。

SHIPPED / EVIDENCE

今回実装したもの

クライアントのしきい値を超えるバイナリ添付は24 MBのチャンクで送信されます。APIは所有者、順序、個数、合計サイズを検証し、ディスク上で組み立てた後、通常のmultipartアップロードと同じ保存ファイル経路へ渡します。

クライアント
24 MB
サーバー上限
32 MB
セッションTTL
24時間
実運用検証
130 MB

01

アプリケーションの上限が本当の上限ではなかった

OpenMakeの自律エージェントタスクは大きなファイルを入力として扱えます。しかし公開リクエストがAPIへ届く前にプロキシで拒否されるなら、アプリケーション側のファイル上限には意味がありません。

Cloudflareの公式文書では、FreeとProゾーンの最大アップロードサイズは100 MBです。単一のmultipartリクエストは、OpenMakeの検証や進行表示が始まる前にエッジでHTTP 413となりました。

02

制約がプロトコルを決めた

最も速い回避策は、プロキシを通らない別のアップロードホストです。しかし既存の公開経路にあるDNS、TLS、認証、デプロイ境界を維持し、リクエストの形を変える方を選びました。

  • 小さなファイルは既存のmultipart経路をそのまま使う。
  • すべてのアップロード操作を認証し、セッションを一人のユーザーに結び付ける。
  • 中断した部分を再試行できるよう、同じインデックスへの再書き込みを安全にする。
  • 組み立て後は既存のstoredPath契約を再利用し、抽出、サンドボックス投入、削除処理を分岐させない。

03

4段階のプロトコルと一度限りのclaim

ブラウザーは最初にファイル名、MIMEタイプ、バイト数、予定チャンク数を宣言します。次にapplication/octet-streamの生チャンクを送り、サーバーへ完了を要求し、最後にuploadId参照でタスクを作成します。

完了処理は冪等です。一方、claimは一度だけです。組み立て済みファイルがタスク用ディレクトリへ移動すると一時セッションが削除され、同じアップロードを別のタスクへ再利用できません。

shell
POST /api/agent-task-uploads
PUT  /api/agent-task-uploads/:id/chunks/0
PUT  /api/agent-task-uploads/:id/chunks/1
POST /api/agent-task-uploads/:id/complete
POST /api/agent-tasks  { files: [{ uploadId: id }] }

04

所有権と整合性はストレージ境界で確認する

サーバーが発行したUUIDごとに、meta.json、番号付きチャンク、組み立て済みファイルを持つディレクトリが作られます。メタデータには所有者と宣言値を記録し、書き込み、完了、claim、中止のたびに認証ユーザーと比較します。

パスのようなID、空または上限超過のチャンク、範囲外インデックス、欠けた部分、宣言サイズと異なる合計を拒否します。すべてを連結した後にだけpartialファイルを確定し、24時間claimされないセッションは新規アップロード時に機会的に削除します。

05

ブラウザーは製品動作ではなく転送方式だけを変える

バイナリ合計が60 MBを超えると、Webクライアントは各ファイルを24 MBずつ送ります。APIのrawパーサー上限32 MBより小さく、転送上の余裕を確保しています。小さな入力は余分な往復を増やさず、従来のmultipartを使い続けます。

完了後のタスク作成はuploadIdだけを持つ小さなJSONです。そこから先の文書抽出とエージェント実行経路は以前と同じです。

06

ユニット、API、ブラウザーの境界を検証した

機能コミットにはチャンクストアのユニットテスト7件とエージェントタスクスイート130件の成功、TypeScriptとESLintのエラー0件が記録されています。復元、冪等な完了、所有者分離、UUIDパス防御、欠落チャンク、サイズ不一致、不正インデックス、完了前claimを確認しました。

実運用APIでは130 MBのファイルを6チャンクでchat.openmake.ccへ送り、タスク作成後に保存ファイルのSHA-256が原本と一致することを確認しました。ブラウザーでは65 MBのPDFを添付し、3回のチャンク送信、uploadIdの作成成功、タスク実行要求の受理まで観察しました。

07

受け入れたトレードオフ

ディスクベースの設計は単純で、アプリケーション再起動後にもファイルが残ります。ただし複数インスタンスへ拡張するには共有アップロードボリュームかセッションアフィニティが必要です。組み立ては一度に一つのサーバーチャンクを直列処理し、最大スループットより予測可能なメモリ使用を優先しました。

宣言サイズで欠落や余分なバイトは検出できますが、公開プロトコルはまだファイルチェックサムを受け取りません。実運用テストでは外部から同一性を証明しましたが、次の版ではその保証を完了処理そのものへ組み込むべきです。

08

次に進めること

再読み込み後に受信済みインデックスをブラウザーが取得できる状態APIが次の有用な層です。ファイルチェックサム、複数インスタンス向けオブジェクトストレージ、明確な一時停止・再開表示を追加すれば、現在の再試行可能な転送を完全な再開型アップロードへ発展させられます。

根拠資料

根拠資料

Engineering Logへ戻る