AI Agents SDE Task Viewer
      • Context
      • Plan
      • Prd
  1. Home
  2. AgentSDE
  3. meridian-backend
  4. gh-14
  5. plan
  6. plan.md
plan.md(2.9 KB)· Apr 2, 2026· 2 min read
  • Summary
  • Files
  • Steps
  • Verification
  • Risks

Plan: Fix SearchIndexService OOM — Rebuild Guard + Memory Cap#

Summary#

SearchIndexService.buildIndex() can run concurrently when rapid file changes trigger overlapping rebuilds (each allocating a full 24K-document index Map). Add an AbortController-based cancellation guard so only one rebuild runs at a time, and add a --max-old-space-size cap as a safety net. The 500 ms debounce on FILE_CHANGE_EVENT already exists in FileWatcherService; no debounce changes needed.

Files#

FileActionDescription
src/modules/search/search-index.service.tsmodifyAdd rebuild guard with AbortController cancellation and rebuildPending flag
ecosystem.config.jscreatePM2 config with --max-old-space-size=512 for production
services/start-backend.shmodifyAdd --max-old-space-size=512 to node exec line
src/modules/search/search-index.service.spec.tsmodifyAdd tests for concurrent rebuild guard and cancellation

Steps#

  1. Add rebuild guard to SearchIndexService — Add private fields: abortController: AbortController | null, rebuildPending: boolean. In handleFileChange() (line 62): if a rebuild is in progress, abort it via abortController.abort(), set rebuildPending = true, and return. In buildIndex(): create a new AbortController, check signal.aborted between file iterations (inside the for (const task of scanResult.tasks) loop at line 276), and bail early if aborted. After buildIndex() completes (or aborts), check rebuildPending — if true, reset the flag and call buildIndex() again.
  2. Skip incremental updates during pending full rebuild — In handleFileChangeDetail() (line 83): if rebuildPending is true, skip the incremental update since the upcoming full rebuild will cover it.
  3. Create ecosystem.config.js — Add PM2 ecosystem config at repo root with app name viewerv2-backend, node_args: '--max-old-space-size=512', script dist/main, and max_memory_restart: '512M'.
  4. Add --max-old-space-size=512 to start-backend.sh — Change line 40 from exec node dist/main to exec node --max-old-space-size=512 dist/main.
  5. Update unit tests — Add spec cases for: (a) concurrent buildIndex() calls result in only one active rebuild, (b) abort signal cancels in-flight rebuild, (c) rebuildPending triggers a follow-up rebuild after the current one completes.

Verification#

  • Run npm run test — all existing + new tests pass
  • Run npm run lint — zero warnings
  • Manual verification: confirm buildIndex() logs show single active rebuild under rapid event simulation

Risks#

  • AbortController check granularity: Checking signal.aborted per-task (not per-file) means a rebuild processes up to one full task's files before aborting. Acceptable tradeoff — per-file checks add overhead for negligible gain with ~24K small markdown files spread across many tasks.
ContextPrd