fix(usage-bar): bound template file cache to prevent unbounded watche…#98990
Conversation
|
Codex review: needs changes before merge. Reviewed July 6, 2026, 4:05 AM ET / 08:05 UTC. Summary PR surface: Source +13, Tests +204, Other +123. Total +340 across 4 files. Reproducibility: yes. Source inspection shows current main and Review metrics: 1 noteworthy metric.
Stored data model Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Next step before merge
Security Review findings
Review detailsBest possible solution: Keep the bounded cache fix, but repair the new watcher-proof test so it uses the shared temp-dir helper correctly and the focused node shard is green before merge. Do we have a high-confidence way to reproduce the issue? Yes. Source inspection shows current main and Is this the best way to solve the issue? No as submitted. The runtime fix is the right narrow owner-module solution, but the new watcher-proof test must pass Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against d0fdfe845b61. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +13, Tests +204, Other +123. Total +340 across 4 files. View PR surface stats
Acceptance criteria:
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (1 earlier review cycle)
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
f69f8f6 to
54da7f8
Compare
2bb1975 to
c978b0f
Compare
6e123f9 to
a5eb6f4
Compare
…r growth Add MAX_CACHED_TEMPLATE_FILES=64 limit; evict the oldest entry (closing its fs.watch watcher) before allocating a watcher for a new key when the cache is full. Eviction runs before watcher allocation so we never create a watcher only to close it immediately. Eviction triggers only when inserting a new key (!fileCache.has(path)) — retries for an existing key must not evict other entries. Fixes openclaw#98960 Co-Authored-By: Claude <[email protected]>
…rn in template.test.ts Co-Authored-By: Claude <[email protected]>
Co-Authored-By: Claude <[email protected]>
What Problem This Solves
Fixes #98960: The module-level
fileCacheMap insrc/auto-reply/usage-bar/template.tsholds a livefs.watchwatcher for each cached template file path. The cache grows without bound — entries are never evicted, and watchers are only closed inclearUsageBarTemplateCacheForTest(). Over time this leaks file descriptors.Root Cause
cacheTemplateFile()inserts without checking cache size. Each new file path creates a persistentfs.watchwatcher that is never released in production.Why This Change Was Made
Add a maximum cache size (
MAX_CACHED_TEMPLATE_FILES = 64). When inserting a new cache key that would exceed the limit, evict the oldest entry (closing itsfs.watchwatcher) before allocating a watcher for the new entry. This bounds watcher count and prevents unbounded FD growth.Key design decisions:
!fileCache.has(path)). Retries for an existing key (re-reading after a prior miss) must not evict other entries.Map.keys().next()for oldest-entry ordering (Map maintains insertion order).Changes
src/auto-reply/usage-bar/template.ts: +13 linesMAX_CACHED_TEMPLATE_FILES = 64constantcacheTemplateFile(), before watcher allocation, guarded by!fileCache.has(path)src/auto-reply/usage-bar/template.test.ts: +79/-1 linescache evictiondescribe blockEvidence
Verification environment
Regression tests (12/12, 2 new)
The two new tests cover:
readFileSyncinstead of serving stale data. Non-evicted entry remains cached.Real-process proof: 65-template load (production code, no mocking)
Standalone script (
scripts/verify-template-cache-bound.mjs) imports the productionloadUsageBarTemplatemodule viatsxand exercises it with 65 real template files. No mocking — this is a real Node process running the actual production code path.Direct watcher create/close measurement (Vitest)
Verification test (
src/auto-reply/usage-bar/template.watcher-proof.test.ts) usesvi.mock+vi.hoistedto interceptfs.watchbefore module resolution and directly count everyFSWatchercreation andclose()call.Measurement methodology:
fs.watchstate.created++per watcher allocatedw.close = fnstate.closed++per watcher closedstate.closedincrements by 1 in Phase 2state.createdincrements by 1 in Phase 2created - closed = 0User Impact
🤖 Generated with Claude Code