Skip to content

perf(registry): throttle the auto-embed ticker's width probe (#677 item 2) - #688

Merged
t0k0sh1 merged 1 commit into
mainfrom
width-probe-throttle-677
Aug 16, 2026
Merged

perf(registry): throttle the auto-embed ticker's width probe (#677 item 2)#688
t0k0sh1 merged 1 commit into
mainfrom
width-probe-throttle-677

Conversation

@t0k0sh1

@t0k0sh1 t0k0sh1 commented Aug 16, 2026

Copy link
Copy Markdown
Owner

Summary

#677(#535監査由来、#682/PR #682で項目1完了済み)の項目2。

refresh_embeddings/refresh_passage_embeddingsは、そのパスで1件も再embedしなかったとき「モデル名据え置きのままproviderの出力幅が変わった(backend swap)」を見逃さないため、width probeを1件だけ余分にproviderへ投げる。この関数はrun_flush_tick(main.rs、既定5秒間隔)からdirtyなcontext単位で毎tick呼ばれるため、書き込みは続くがgloss本文(name+上位GLOSS_FACTS件のfact)は動かない、という成熟したcontextで最も普通の状態で、probe呼び出しが無期限に積み上がっていた。

やったこと: providerの出力幅はcontextごとの性質ではなくprovider自身の性質、という事実を使ってprobeを間引いた。

  • Inner::observed_embed_width: プロセス全体で共有する「直近に実際に観測したproviderの幅」。記録はtimed_embed_for_refresh(refresh系のembed呼び出しが全て通る唯一のチョークポイント)の1箇所のみ。
  • provider_width_recently_confirmed: 観測が新しく(WIDTH_OBSERVATION_TRUST=60秒)、かつcarried幅と一致するかどうかの判定。LOAD_FAILURE_RETRY/still_quarantinedと同じ形。
  • スロットルはティッカー専用の新規エントリポイント(auto_refresh_embeddings/auto_refresh_passage_embeddingsmain.rsのフラッシャーが呼ぶ)にのみ適用。既存の公開refresh_embeddings/refresh_passage_embeddings(HTTPリフレッシュエンドポイント、および全ての直接呼び出し)は変更なしで常にprobeする。

なぜスコープを分けたか: 当初は公開関数自体を無条件でスロットルしたが、tests/http_api/width_probe.rsのE2Eテスト(「1回のリフレッシュで検知・修復まで完了する」契約)がすぐに落ちた。60秒のtrust windowの間に明示的なリフレッシュ呼び出しが来ると、直前の(スワップ前の)観測を信頼してprobeをスキップしてしまい、まさに検知させたいbackend swapを見逃す。オペレーターが「なぜ検索が動かないか」を診断してリフレッシュを叩く操作は稀かつ意図的で、そこでの1回余分なprovider呼び出しは無視できるコストである一方、「1回のリフレッシュで確実に直る」という契約はそちらでこそ重要。issue自体もコストの発生源としてmain.rsのティッカー呼び出しを名指ししており(自動リフレッシュのみが問題)、このスコープ分けは issue の記述にも整合する。

項目3(vector sidecarにTTL検疫が無い件)は、issue本文自ら「疑い、実害未検証」としており、実インシデントか実測が出るまで対象外(ユーザー判断)。#677はこの項目を残してOPENのまま。

Test plan

  • cargo fmt
  • cargo clippy --all-targets --locked -- -D warnings
  • cargo nextest run --locked (3852 passed、width_probe.rsのE2E契約含む)
  • cargo test --doc --locked
  • diff-scoped mutation gate: 41件(予算25件を超過、ただし前例の「無関係な巨大関数への巻き込み」ではなく実質すべて新規/変更コード自体だったため--exclude-reは使わずローカルで全件実行) — 34 caught, 7 unviable, missed 0件

Refs #677

https://claude.ai/code/session_0198T2iKZ17g3tt2bdNq1ju8

Summary by CodeRabbit

  • 改善

    • 自動埋め込み更新時の不要なプロバイダー呼び出しを削減しました。
    • 直近に確認したベクトル幅を一定期間再利用し、必要な場合のみ再確認します。
    • グラフおよび段落の自動更新を効率化しました。
  • バグ修正

    • ベクトル幅の変更を引き続き検出し、必要に応じて再埋め込みするよう改善しました。

…em 2)

A busy, gloss-stable context paid one provider round trip (the width
probe that guards against a silent backend swap under an unchanged
model name) on every 5s flush tick, forever — refresh_embeddings and
refresh_passage_embeddings both run per dirty context per tick, and a
context whose writes never touch its top-N gloss facts stays a no-op
refresh indefinitely.

The provider's output width is its own property, not any one
context's, so a process-wide "most recently observed width" (Inner::
observed_embed_width, recorded at timed_embed_for_refresh's one choke
point) lets a refresh skip its own probe once a recent-enough
observation already agrees with what it carries
(provider_width_recently_confirmed, WIDTH_OBSERVATION_TRUST = 60s).

The throttle is scoped to two new ticker-only entry points
(auto_refresh_embeddings/auto_refresh_passage_embeddings) that main.rs's
flusher calls instead. The existing public refresh_embeddings/
refresh_passage_embeddings — used by the HTTP refresh endpoint and
every direct caller — are untouched and keep probing unconditionally,
so an explicit refresh still reliably detects and heals a width change
in one call, the contract tests/http_api/width_probe.rs pins.

Item 3 (no TTL quarantine on vector-sidecar load failures) stays out of
scope — the issue itself frames it as unverified real-world impact, not
a known defect — so #677 stays open with that item.

Refs #677

Claude-Session: https://claude.ai/code/session_0198T2iKZ17g3tt2bdNq1ju8
@coderabbitai

coderabbitai Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 33909ac1-9949-4cf1-a146-66011f610178

📥 Commits

Reviewing files that changed from the base of the PR and between e4770df and 6f9d1a5.

📒 Files selected for processing (6)
  • src/main.rs
  • src/registry.rs
  • src/registry/boot.rs
  • src/registry/embeddings.rs
  • src/registry/embeddings/gloss_tests.rs
  • src/registry/embeddings/passage_tests.rs

Included review availability: 1 review is currently available. Based on recent review activity, included reviews refill at 2 per hour.


📝 Walkthrough

Walkthrough

自動埋め込み更新に専用メソッドを追加しました。直近のプロバイダー幅観測を共有し、信頼期間内の幅プローブを省略します。明示更新は従来どおり毎回プローブします。関連するグロス、パッセージ、幅変更のテストを追加しました。

Changes

埋め込み自動更新

Layer / File(s) Summary
埋め込み幅観測の状態管理
src/registry.rs, src/registry/boot.rs
StateInner が直近の埋め込み幅と観測時刻を保持します。観測結果の共有、60秒の信頼期間判定、テスト用の時刻調整を追加しました。
更新経路とプローブ制御
src/registry/embeddings.rs
明示更新と自動更新の内部処理を分離しました。自動更新は、保持幅と一致する有効な観測がある場合に幅プローブを省略します。
フラッシュ統合と更新検証
src/main.rs, src/registry/embeddings/gloss_tests.rs, src/registry/embeddings/passage_tests.rs
フラッシュ処理を自動更新メソッドへ切り替えました。連続更新、共有観測、観測期限後の幅変更検出と再埋め込みを検証します。

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to 6f9d1

The change reduces redundant provider width probes during automatic refreshes while preserving immediate probing for explicit refresh requests; no actionable merge-blocking risk remains after normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant Flush
  participant Registry
  participant Provider
  Flush->>Registry: auto_refresh_embeddings または auto_refresh_passage_embeddings
  alt 幅観測が60秒以内で保持幅と一致
    Registry->>Registry: 幅プローブを省略
  else 観測なしまたは期限切れ
    Registry->>Provider: 幅プローブを実行
    Provider-->>Registry: 埋め込みベクトル幅
    Registry->>Registry: 観測幅と時刻を共有
  end
  Registry->>Provider: 必要な項目を自動埋め込み
Loading

Possibly related PRs

  • t0k0sh1/taguru#574: レジストリの埋め込み幅追跡と変更処理に関連します。
  • t0k0sh1/taguru#682: グロスおよびパッセージの埋め込み更新フローに関連します。
  • t0k0sh1/taguru#467: グロスおよびパッセージの埋め込み更新テストに関連します。
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed タイトルは、自動埋め込み処理の幅プローブを抑制する主要変更を正確かつ簡潔に示しています。
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch width-probe-throttle-677

Comment @coderabbitai help to get the list of available commands.

@t0k0sh1
t0k0sh1 merged commit c48c1d0 into main Aug 16, 2026
15 checks passed
@t0k0sh1
t0k0sh1 deleted the width-probe-throttle-677 branch August 16, 2026 06:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant