LearnNewsExamplesServices
Frontmatter
id7637
titleFix: Race condition in async service initialization
stateClosed
labels
bugai
assigneestobiu
createdAtOct 25, 2025, 10:21 AM
updatedAtOct 25, 2025, 10:51 AM
githubUrlhttps://github.com/neomjs/neo/issues/7637
authortobiu
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtOct 25, 2025, 10:51 AM

Fix: Race condition in async service initialization

Closed v11.0.0 bugai
tobiu
tobiu commented on Oct 25, 2025, 10:21 AM

There is a race condition during the startup of MCP servers (e.g., memory-core) that rely on singleton services with asynchronous initialization.

Problem:

  • The main server entry point (mcp-stdio.mjs) imports services at startup.
  • Services like ChromaManager extend core.Base and perform async setup (like database connections) in initAsync().
  • core.Base calls initAsync() in a non-blocking way from the construct() method.
  • Other services (e.g., HealthService) are called immediately in the startup sequence, before initAsync() is guaranteed to have completed, leading to failed checks and incorrect "unhealthy" status reports.

Solution: Enhance Neo.core.Base to provide a standardized and reliable way to await the completion of an instance's asynchronous initialization.

  1. Introduce an awaitable ready() method to Neo.core.Base:

    • Add private #readyPromise and #readyResolver fields to core.Base.
    • In the construct() method, initialize the promise.
    • Add a public ready() method that returns this promise.
  2. Centralize Ready Logic in afterSetIsReady:

    • Create an afterSetIsReady(value, oldValue) hook in core.Base.
    • When isReady becomes true, this hook will:
      • Resolve the #readyPromise.
      • For observable classes (static observable = true), fire a ready event, passing the instance as the payload.
    • Update the JSDoc for the isReady_ config to reflect this new behavior.
  3. Refactor consumers:

    • Update ai/mcp/server/memory-core/mcp-stdio.mjs to use await ChromaManager.ready() before performing the initial health check.

This change will provide a clean, reusable, and framework-aligned solution for managing async initialization in Neo.mjs classes.

tobiu assigned to @tobiu on Oct 25, 2025, 10:50 AM
tobiu added the bug label on Oct 25, 2025, 10:51 AM
tobiu added the ai label on Oct 25, 2025, 10:51 AM
tobiu referenced in commit 0b1bc90 - "Fix: Race condition in async service initialization #7637" on Oct 25, 2025, 10:51 AM
tobiu closed this issue on Oct 25, 2025, 10:51 AM