← Back to PRs

#17657: fix: clear QMD manager cache on in-process restart (SIGUSR1)

by IrriVisionTechnologies open 2026-02-16 02:06 View on GitHub →
gateway cli stale size: XS
## Problem The `QMD_MANAGER_CACHE` (module-level `Map` in `search-manager.ts`) persists across in-process restarts triggered by SIGUSR1. Config changes to QMD scope, collections, command path, or other memory settings do not take effect until a full process kill (`kill -9`). ### Reproduction Steps 1. Set `memory.qmd.scope.default: "deny"` (the default) 2. Start the gateway 3. Verify `memory_search` is denied in guild channels (expected) 4. Patch config: `memory.qmd.scope.default: "allow"` 5. Gateway restarts via SIGUSR1 6. `memory_search` is **still denied** in guild channels (bug) 7. Only `kill -9` + restart makes the scope change take effect ### Root Cause `getMemorySearchManager()` caches managers in a module-level `Map` keyed by `agentId + serialized config`. After SIGUSR1, the gateway reloads config, but the old cached manager (created with the pre-restart config) is still returned for existing sessions because the module-level Map survives the in-process restart. ## Fix - Export `clearQmdManagerCache()` from `search-manager.ts` that properly closes all cached managers and clears the Map - Call it from the restart iteration hook in `run-loop.ts`, alongside the existing `resetAllLanes()` call This ensures QMD scope, collection, and command changes take effect immediately after `config.patch` / `config.apply` restarts. ## Changes - `src/memory/search-manager.ts`: Add `clearQmdManagerCache()` export - `src/cli/gateway-cli/run-loop.ts`: Import and call on restart iteration ## Testing Manually verified on production instance: 1. Changed `scope.default` from `deny` → `allow` 2. Before fix: required `kill -9` to take effect 3. After fix: `config.patch` restart applies immediately Related: #15093 (QMD reliability improvements) <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR fixes a bug where the module-level `QMD_MANAGER_CACHE` in `search-manager.ts` persists across in-process restarts (SIGUSR1), causing memory config changes (scope, collections, command path) to not take effect until a full `kill -9`. The fix introduces `clearQmdManagerCache()` and invokes it from two restart paths: - **SIGUSR1 in-process restart** (`run-loop.ts`): called in the restart iteration hook alongside `resetAllLanes()` - **Hot-reload via config file watcher** (`server-reload-handlers.ts`): called when `plan.restartMemory` is true, enabled by a new `"memory"` prefix hot-reload rule in `config-reload.ts` The implementation follows the established patterns for other subsystem restarts (cron, heartbeat, browser-control). New tests verify that `memory.*` config changes produce a hot-reload plan rather than requiring a full gateway restart. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge — it adds a targeted cache-clearing mechanism with no impact on the happy path. - The changes are minimal and well-scoped: a new export function that clears a module-level Map, integrated into two existing restart paths following established patterns. The code is correct (Map delete-during-iteration is spec-safe in JS, fire-and-forget close is appropriate for restart paths). Tests cover the config-reload plan logic. No regressions are likely since clearQmdManagerCache only runs during restart/reload events and the existing getMemorySearchManager logic is unchanged. - No files require special attention. <sub>Last reviewed commit: 00ce621</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs