Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions KNOWN_ISSUES.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,25 @@
意味し、そのエントリこそ chat proxy の fail-open 経路が配信する
当のものだから (同ファイルの `failOpen`)。

### chat 経路の障害検知レイテンシに上限がない
### chat 経路の障害検知はリクエストごとにバジェット分を支払う

- 場所: `services/haru-server/src/app.ts` (`cachedSnapshot` が
`getFleetRoutePointer` を呼ぶ箇所)。
- 現状: pointer 読み取りに timeout / AbortSignal がなく、障害状態の
メモ化もない。そのためハング型の障害 (TCP は受けるが応答しない)
では、fail-open が発動する前に毎リクエストがトランスポート自身の
失敗を待つ (最悪 undici のヘッダータイムアウトまで、リクエスト
ごとに TTFB として支払う)。即時失敗型の障害 (connection refused)
はほぼ即座で影響なし
- 先送りの理由: 検知の上限は設計判断 (固定バジェット / 設定ノブ /
サーキットブレーカー) であり、このスライスは意図的に新しい env
ノブを増やさない。よくある障害モード (エンドポイント停止) は
即時失敗する。
- 意図する修正: pointer 読み取りへの小さな固定 AbortSignal
バジェット (健全時 p99 より十分上)。加えて短寿命の「store 停止中」
メモで後続リクエストを直接キャッシュへ向かわせてもよい。いずれも
「fail-open を許可するのは pointer 読み取りの失敗だけ」という
規則を保つこと
- 現状: トランスポート側には上限が入った。`@haru/db` の
`createDatabase` が `DEFAULT_QUERY_BUDGET_MS` でクエリごとに
AbortSignal を付けるため、ハング型の障害 (TCP は受けるが応答
しない) は undici の既定ではなくバジェットで reject し、その
reject は fail-open を許可するトランスポート失敗として
`cachedSnapshot` に届く。残るのは障害状態のメモ化が無いこと
最初の1リクエストが代表して支払うのではなく、毎リクエストが
TTFB としてバジェット分を支払い続ける。即時失敗型の障害
(connection refused) はいずれにせよほぼ即座。
- 先送りの理由: 残り半分はポリシー判断 (「store 停止中」メモを
どれだけ信頼してよいか、何が解除するか) であり、このスライスは
意図的に新しい env ノブを増やさない。
- 意図する修正: 短寿命の「store 停止中」メモで後続リクエストを
直接キャッシュへ向かわせる。「fail-open を許可するのは pointer
読み取りの失敗だけ」という規則は保つこと

### fail-closed の chat エラーはリクエストごとにログされる

Expand Down
32 changes: 16 additions & 16 deletions KNOWN_ISSUES.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,25 @@ deferred, and the intended fix. Entries should be deleted when fixed.
entry is exactly what the chat proxy's fail-open path serves from
(see `failOpen` in the same file).

### Outage detection latency on the chat path is unbounded
### Outage detection on the chat path costs one budget per request

- Where: `services/haru-server/src/app.ts` (`cachedSnapshot` calling
`getFleetRoutePointer`).
- Current: the pointer read has no timeout or AbortSignal and there is
no memoized outage state, so during a hang-mode outage (the store
accepts TCP but never answers) every chat request waits for the
transport's own failure before fail-open engages, potentially the
full undici header timeout, paid per request as time-to-first-byte.
A fast-fail outage (connection refused) is near-instant and
unaffected.
- Why deferred: a detection bound is a design decision (fixed budget
vs config knob vs circuit breaker) and this slice deliberately adds
no new env knobs; the common outage mode (endpoint down) fails fast.
- Intended fix: a small fixed AbortSignal budget around the pointer
read (well above healthy p99), optionally with a short-lived "store
is down" memo so consecutive requests skip straight to the cache.
Both must preserve the rule that only a FAILING pointer read
licenses fail-open.
- Current: the transport half is now bounded.
`DEFAULT_QUERY_BUDGET_MS` in `@haru/db`'s `createDatabase` gives every
query its own AbortSignal, so a hang-mode outage (the store accepts
TCP but never answers) rejects at the budget instead of at undici's
default, and the rejection reaches `cachedSnapshot` as the transport
failure that licenses fail-open. What remains is that there is still
no memoized outage state, so each request pays the budget again as
time-to-first-byte rather than the first one paying it for the rest.
A fast-fail outage (connection refused) is near-instant either way.
- Why deferred: the remaining half is a policy decision (how long a
"store is down" memo may be trusted, and what clears it) and this
slice deliberately adds no new env knobs.
- Intended fix: a short-lived "store is down" memo so consecutive
requests skip straight to the cache, preserving the rule that only a
FAILING pointer read licenses fail-open.

### Fail-closed chat errors log once per request

Expand Down
Loading