• Status: Accepted
  • Mode: Standard
  • Kruchten Type: Existence/Property
  • Scope: platform
  • Implementation Status: Done
  • 起案者: [email protected]
  • 起案日時 (JST): 2026-05-28 05:46
  • 承認日時 (JST): 2026-06-21
  • Deciders: [email protected] (単独)

コンテキスト

1.1 背景

Gate 2 (consistency.ts) は毎回 GitHub API で全 ADR ファイル一覧と内容を取得している。ADR 件数の増加とともに、Pipeline 実行ごとの GitHub API 負荷が累積的に増加してきたため、キャッシュ層導入の議論を開始した。

1.2 現状

80+ ADR ファイル。fetchAdrSummaries は毎回 REST + GraphQL で全件取得している。

1.3 課題

(1) 5 ドラフト投入で 10 subrequest 発生。(2) レスポンス ~200KB。(3) rate limit 消費非効率。

1.4 制約・要件

  • Workers KV (eventually consistent、TTL ベースキャッシュ)
  • ADR 変更頻度: 日 0-3 件、TTL 1 時間で十分
  • 既存 consistency.ts の判定ロジック不変

1.5 目標

fetchAdrSummaries の結果を DRAFTS_KV に TTL 付きでキャッシュする。新規 ADR マージ直後のキャッシュ無効化は手動 Runbook + 将来的な自動化で対応する。

1.6 KV Eventually Consistent 特性への対処 (#reliable の根拠)

Cloudflare KV は eventually consistent だが、本ユースケースでの影響は以下の理由で限定的:

(1) 整合性ウィンドウの定量評価: Cloudflare の KV 伝播遅延は通常 60 秒以内 (cf. Cloudflare docs: "changes are usually visible globally within 60 seconds")。TTL=3600s に対し伝播遅延 60s は 1.7% の追加不整合ウィンドウであり、実用上無視可能。

(2) 手動無効化後の read-after-write: DELETE _cache:adr-summaries 後の次回 fetchAdrSummaries は cache miss → GitHub API fetch → KV put → 最新データ取得。同一 Worker instance 内の read-after-write は KV の仕様上一貫性が保証される (same colo, same request path)。ただし Gate 1 盲点 #4 指摘のとおり、DELETE → 次回 fetchAdrSummaries はクロスリクエストシナリオであり、同一リクエストスコープ内の保証は適用されない可能性がある。Cloudflare KV ドキュメントの正確な引用と、クロスリクエストでの保証有無の精査は実装フェーズで完了させる(要追記)。

(3) 誤通過の影響評価: 仮にキャッシュが古い ADR 一覧を返した場合、最悪ケースは「新規 ADR との CONFLICT/SUPERSEDE が検出されない」。これは Gate 3 (Parallel Review) と Gate 4 (Scoring) で代替検出可能 (多層防御)。かつ ADR 起案頻度 (月 5-8 件) と TTL (1h) を考慮すると、同日に ADR マージ + 別 ADR pipeline 投入が重なる確率は月 1-2 回程度。ただし Gate 1 盲点 #5 のとおり「Gate 3・Gate 4 は Gate 2 の完全な代替ではなく補完」と位置づける。

(4) Force refresh 確実化: DELETE 後に即座に GET /drafts/_cache:adr-summaries で 404 を確認するスクリプトを Runbook に記載し、運用者が伝播完了を検証可能にする。複数リージョンの Worker endpoint に対する 404 確認手順も Runbook に含める。

1.7 ステークホルダー

  • Pipeline 利用者: Gate 2 応答時間改善
  • ADR 起案者: 新規 ADR マージ直後の最大 1 時間不整合(手動無効化で回避可能)

1.8 過去 ADR との関係

ADR関係
ADR-0019 (LangGraph 基盤)Confirms
ADR-0037 (KV draft staging)Confirms — DRAFTS_KV namespace 共用、_cache: prefix 分離
ADR-0077 (Telemetry)Confirms (盲点 #3 反映により Neutral から変更) — キャッシュ可観測性のメトリクス計装を必須化

Review After: 2026-08-28 (3 ヶ月後)

決定

DRAFTS_KV namespace に _cache:adr-summaries キーで TTL=3600s のキャッシュを保持し、cache miss 時のみ GitHub API で fetchAdrSummaries を実行する。手動無効化は DELETE /drafts/_cache:adr-summaries + 404 確認スクリプトで実施し、将来的に GitHub Actions による自動無効化への移行を計画する。テレメトリ計装 (cache_hit/miss/invalidate、cached_at、X-Cache-Age) を ADR-0077 パイプラインに接続し、可観測性を確保する。

判断基準 (Decision Drivers)

3.1 評価軸 (Q42 9 タグから 3-5 個選定)

重要度ラベル係数: Must ×2.0 / High ×1.0 / Medium ×0.5

#重要度 (係数)案件特有の解釈
1#reliable[Must] (×2.0)キャッシュが古いデータを返しても CONFLICT/SUPERSEDE 検出に致命的影響を与えないこと。KV 伝播遅延が許容範囲内であること
2#efficient[Must] (×2.0)GitHub API rate limit 消費を実質的に削減すること。subrequest 数とペイロードサイズの削減
3#operable[High] (×1.0)キャッシュ無効化が運用者に理解しやすく、Runbook 通り実行可能であること。可観測性が担保されること
4#maintainable[High] (×1.0)既存 consistency.ts への変更を最小化し、将来の ADR 件数増加に耐えうる構造であること
5#secure[Medium] (×0.5)キャッシュデータの機密性が ADR-0037 アクセス制御ポリシーに準拠すること

K.O. criterion: Must 軸の score < 3 は不採用。

3.2 評価軸 × 案スコア表

係数採択案 (A)案 B (ETag)案 C (Cache API)案 D (現状維持)
#reliable×2.04545
#efficient×2.04241
#operable×1.03235
#maintainable×1.04234
#secure×0.53435
加重和 (正規化)0.7550.6050.7110.689
K.O. 通過 (Must ≥3)❌ (#efficient=2)❌ (#efficient=1)

加重和は K.O. 通過候補のタイブレーク用。案 A は K.O. 通過かつ最高スコア。

検討した代替案 (Alternatives Considered)

  • 案 A【採用】: DRAFTS_KV に _cache:adr-summaries キーで TTL=3600s キャッシュ。miss 時のみ GitHub API。手動無効化は DELETE + 404 確認。影響: consistency.ts のみ。工数 ~1.5h (Gate 1 盲点 #10 を反映し再見積もり 4-6h、要追記)。KV 伝播遅延は 60s 以内で実用上無視可能 (cf. §1.6)。
  • 案 B: ETag 条件付きリクエスト — 不採用: GraphQL は ETag 非対応。
  • 案 C: Workers Cache API — 不採用: 自前 JSON キャッシュには KV が適切。
  • 案 D: 現状維持 — 不採用: rate limit 消費非効率が継続。ただし盲点 #8 のとおり実消費量の定量データが未提示のため、実装前に過去 30 日間の rate limit 消費ログを確認し本決定の妥当性を再検証する (要追記)。

影響 (Consequences)

5.1 正の影響 (Good)

  • GitHub API subrequest 数の削減 (5 ドラフト投入時 10 → ~2、TTL 内 cache hit 時)
  • Gate 2 応答時間の短縮 (~200KB のネットワーク往復除去)
  • rate limit 消費の削減によりピーク時の枯渇耐性向上
  • テレメトリ計装により Gate 2 整合性チェックの可観測性が向上 (ADR-0077 Confirms)

5.2 負の影響 (Bad)

  • キャッシュ可観測性の欠如リスク (盲点 #3): 計装が不十分な場合、キャッシュ起因の誤判定とロジックバグの切り分けが不能になる。X-Cache-Age 出力と structured log を必須化することで緩和。
  • 手動無効化 Runbook の形骸化リスク (盲点 #2): 月 15-24 回の手動操作機会で人的ミスが発生しうる。GitHub Actions による自動無効化 workflow への移行を Phase 2 として計画 (要追記: 移行期限)。
  • DRAFTS_KV 共用によるキャッシュ汚染リスク (盲点 #1): 既存 draft 管理スクリプトの一括 flush が _cache: キーを巻き込む可能性。実装前に既存スクリプト全件をレビューし、KV list 操作に prefix='draft:' の明示フィルタを追加。専用 CACHE_KV namespace 化のコスト評価も実施 (要追記)。
  • read-after-write 保証の根拠の精査不足 (盲点 #4): Cloudflare KV ドキュメントの正確な引用が未完了。実装フェーズで完了させ、保証されない場合は Runbook に 60s 待機を明記。
  • 工数過小見積もりリスク (盲点 #10): thundering herd 対策・テレメトリ・自動無効化 CI・統合テストを含めた再見積もり 4-6h を起案者承認後に確定 (要追記)。

5.3 中立・トレードオフ (Neutral / Trade-offs)

  • 多層防御前提の確証バイアス (盲点 #5): Gate 3・Gate 4 は Gate 2 の完全な代替ではなく補完。各 Gate の責任範囲を README に明記し、Gate 3・Gate 4 の CONFLICT/SUPERSEDE 検出テストケースを CI に追加。
  • O(N) スケール問題 (盲点 #6): 単一キャッシュエントリ設計のため、1 件追加でも全体無効化。1 年後 100 件・2 年後 150 件のペイロード増加に備え、Review 条件として ADR 件数 150 件到達・ペイロード 500KB 超・p95 レイテンシ・KV 読み取り率・GitHub API 消費率を評価指標として設定 (要追記)。
  • Thundering herd 問題 (盲点 #7): TTL 切れ・無効化直後の並列 cache miss で同時 GitHub API 呼び出しが発生しうる。singleflight パターンの実装可否と rate limit 残量の Telemetry 監視を実装フェーズで検討。
  • rate limit 消費の定量根拠不足 (盲点 #8): 現状の GitHub API 消費量と rate limit への近接度データが未提示。実装前に過去 30 日間の X-RateLimit-Used ログまたは ADR-0077 Telemetry データで定量化する (要追記)。
  • キャッシュデータ機密性 (盲点 #9): キャッシュ対象フィールドを titlestatusid に限定し、本文・コメント等の機密性の高い情報は除外。ADR-0037 アクセス制御ポリシーの _cache: prefix への適用を明示文書化。

撤退条件 (Rollback Plan)

判定指標閾値期限対応
キャッシュ起因の誤通過インシデント月 2 件以上Review After (2026-08-28)キャッシュ無効化・コード revert・案 D 復帰
KV 伝播遅延p95 > 300s が継続1 ヶ月TTL を 300s に短縮または案 D 復帰
ペイロードサイズ> 500KBReview After軽量スキーマ (title+status+id) に変更
ADR 件数> 150 件Review After差分キャッシュ設計に再設計
GitHub API rate limit 残量< 1000 req/h で頻発1 ヶ月singleflight 実装・並列度抑制

撤退手順:

  1. wrangler kv:key delete --binding=DRAFTS_KV "_cache:adr-summaries" でキャッシュ削除
  2. consistency.ts のキャッシュ参照コードを feature flag で無効化 → revert PR
  3. ADR-0077 Telemetry で cache_hit 率 0% を確認
  4. 影響範囲: Gate 2 応答時間は元に戻るが、機能は完全復元

Confirmation (準拠確認 / Fitness Function)

要素内容
検証手段 1scripts/adr-lint.mjs 拡張: consistency.ts が _cache: prefix 付きキーのみを操作し、draft: prefix を一括 flush していないことを静的解析で確認
検証手段 2統合テスト (tests/gate2-cache.test.ts): (a) cache hit/miss 経路の正常動作、(b) DELETE 後の next fetch が GitHub API を呼ぶこと、(c) TTL 経過後の自動再取得
検証手段 3ADR-0077 Telemetry ダッシュボード: cache_hit_ratecache_age_p95github_api_subrequest_countrate_limit_remaining を週次でレビュー
検証手段 4Gate 3・Gate 4 の CONFLICT/SUPERSEDE 検出テストケース (CI 定期実行) により多層防御の実効性を継続確認
実行頻度静的解析: 全 PR / 統合テスト: 全 PR + nightly / Telemetry レビュー: 週次 / 多層防御テスト: 日次
違反時の対応(a) 静的解析・統合テスト失敗 → PR ブロック / (b) cache_hit_rate < 50% が 1 週間継続 → TTL 見直し / (c) 多層防御テスト失敗 → Gate 2 キャッシュ無効化 + Incident チケット起票 / (d) Review After までに評価指標 (§5.3) のいずれか閾値超過 → 撤退条件発動

参照 (References)

  • 関連 ADR: ADR-0019 (LangGraph 基盤, Confirms), ADR-0037 (KV draft staging, Confirms), ADR-0077 (Telemetry, Confirms)
  • 関連 PR/Issue: - (要追記)
  • 外部資料: Cloudflare Workers KV docs ("changes are usually visible globally within 60 seconds"), Suhr 1999 CBA criterion