Skip to content

fix(poller): cap per-commit file count in the diff path against the subrequest budget #238

Description

@smileygames

purpose

diff path に per-commit の file 上限が無く、file 数の多い commit が単独で Worker の 1 invocation あたり subrequest 予算(1000)に迫りうる。#236 が閉じた token 軸と同じ形で diff surface が恒久停止する経路なので、file 数軸にも上限を入れる。

premise

Too many subrequests by single Worker invocation は仮説ではなく、この worker の production で現に発生している(#236 本文の観測、および wiki 取得経路 fetchWikiContent)。

per-file のコストは src/pipeline/embed-diff.ts で 2 subrequest。

  • upsertFtsRow(D1 FTS mirror)— L235
  • storeStub.fetch(Durable Object への DiffRecord 記録)— L295

これに batch 単位のコストが加わる。1 batch あたり 2 subrequest(Workers AI call と VECTORIZE.upsert)。GitHub の commit detail API は 1 commit あたり最大 300 file を返す。

src/poller.ts の cap は commit 数にしか掛かっていない。

  • MAX_DIFF_COMMITS_FORWARD_PER_RUN = 5
  • MAX_DIFF_COMMITS_BACKWARD_PER_RUN = 5

file 数側の cap は diff path のどこにも存在しない。しかも cron 1 tick は 1 invocation で全 repo・全 surface を処理するため、subrequest 予算は docs / wiki / issue / release 経路と共有されている。

なぜ stall するか

#178 の watermark 不変条件により、取り込みに成功していない commit を watermark は追い越さない。subrequest 枯渇で file の upsert が失敗すると failed に計上され、その commit は未取り込みとして扱われる。file 数が原因である以上、次の cron でも同じ commit が同じ file 数で再試行されるので、失敗は決定論的。#236 で修正した token 軸とまったく同じ停止の形になる。

不変条件側は正しい。上限を持たない側が欠陥である。

constraints

  • watermark 不変条件は変更しない
  • file を落とさない。上限は「1 run で処理する file 数」の分割であって、間引きではない。1 commit を複数 run にまたがって処理する場合、その commit の watermark は完了まで前進させない(不変条件と整合させる)
  • subrequest 予算は invocation 全体で共有されているため、diff path だけの局所最適にしない。少なくとも「diff path が予算をどれだけ使ってよいか」を明示する形にする
  • 要件記述(docs/0-requirements.md / docs/0-requirements.ja.md)を同一 PR で更新する

target files

  • src/poller.ts — per-commit file 上限と、部分処理時の watermark 保持
  • src/pipeline/embed-diff.ts — 呼び出し側の分割受け入れ
  • docs/0-requirements.md / docs/0-requirements.ja.md — Diff Pipeline 節
  • テスト — 上限超過 commit が分割され、完了まで watermark が前進しないこと

acceptance

  • file 数の多い commit が単独で invocation 予算を使い切らない
  • 部分処理された commit の watermark が前進しない
  • 既存テストが通り、回帰テストが追加されている

経緯

#236 の実装中に 2 回にわたり報告された隣接ギャップ。#236 の literal 外のため分離した。

Metadata

Metadata

Assignees

Labels

bug動いていない、壊れているready本文が実装開始できる形まで収束している状態。ただし更新は継続可能review-pending実装フェーズ完了。orchestration (brake eval / review / merge / close) 待ち

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions