Gateway: eager-init QMD backend on startup

This commit is contained in:
Vignesh Natarajan
2026-02-07 19:38:04 -08:00
committed by Vignesh
parent ef4a0e92b7
commit efc79f69a2
5 changed files with 97 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import type { OpenClawConfig } from "../config/config.js";
const { getMemorySearchManagerMock } = vi.hoisted(() => ({
getMemorySearchManagerMock: vi.fn(),
}));
vi.mock("../memory/index.js", () => ({
getMemorySearchManager: getMemorySearchManagerMock,
}));
import { startGatewayMemoryBackend } from "./server-startup-memory.js";
describe("startGatewayMemoryBackend", () => {
beforeEach(() => {
getMemorySearchManagerMock.mockReset();
});
it("skips initialization when memory backend is not qmd", async () => {
const cfg = {
agents: { list: [{ id: "main", default: true }] },
memory: { backend: "builtin" },
} as OpenClawConfig;
const log = { info: vi.fn(), warn: vi.fn() };
await startGatewayMemoryBackend({ cfg, log });
expect(getMemorySearchManagerMock).not.toHaveBeenCalled();
expect(log.info).not.toHaveBeenCalled();
expect(log.warn).not.toHaveBeenCalled();
});
it("initializes qmd backend for the default agent", async () => {
const cfg = {
agents: { list: [{ id: "ops", default: true }, { id: "main" }] },
memory: { backend: "qmd", qmd: {} },
} as OpenClawConfig;
const log = { info: vi.fn(), warn: vi.fn() };
getMemorySearchManagerMock.mockResolvedValue({ manager: { search: vi.fn() } });
await startGatewayMemoryBackend({ cfg, log });
expect(getMemorySearchManagerMock).toHaveBeenCalledWith({ cfg, agentId: "ops" });
expect(log.info).toHaveBeenCalledWith(
'qmd memory startup initialization armed for agent "ops"',
);
expect(log.warn).not.toHaveBeenCalled();
});
it("logs a warning when qmd manager init fails", async () => {
const cfg = {
agents: { list: [{ id: "main", default: true }] },
memory: { backend: "qmd", qmd: {} },
} as OpenClawConfig;
const log = { info: vi.fn(), warn: vi.fn() };
getMemorySearchManagerMock.mockResolvedValue({ manager: null, error: "qmd missing" });
await startGatewayMemoryBackend({ cfg, log });
expect(log.warn).toHaveBeenCalledWith(
'qmd memory startup initialization failed for agent "main": qmd missing',
);
expect(log.info).not.toHaveBeenCalled();
});
});

View File

@@ -0,0 +1,24 @@
import type { OpenClawConfig } from "../config/config.js";
import { resolveDefaultAgentId } from "../agents/agent-scope.js";
import { resolveMemoryBackendConfig } from "../memory/backend-config.js";
import { getMemorySearchManager } from "../memory/index.js";
export async function startGatewayMemoryBackend(params: {
cfg: OpenClawConfig;
log: { info?: (msg: string) => void; warn: (msg: string) => void };
}): Promise<void> {
const agentId = resolveDefaultAgentId(params.cfg);
const resolved = resolveMemoryBackendConfig({ cfg: params.cfg, agentId });
if (resolved.backend !== "qmd" || !resolved.qmd) {
return;
}
const { manager, error } = await getMemorySearchManager({ cfg: params.cfg, agentId });
if (!manager) {
params.log.warn(
`qmd memory startup initialization failed for agent "${agentId}": ${error ?? "unknown error"}`,
);
return;
}
params.log.info?.(`qmd memory startup initialization armed for agent "${agentId}"`);
}

View File

@@ -22,6 +22,7 @@ import {
scheduleRestartSentinelWake,
shouldWakeFromRestartSentinel,
} from "./server-restart-sentinel.js";
import { startGatewayMemoryBackend } from "./server-startup-memory.js";
export async function startGatewaySidecars(params: {
cfg: ReturnType<typeof loadConfig>;
@@ -150,6 +151,10 @@ export async function startGatewaySidecars(params: {
params.log.warn(`plugin services failed to start: ${String(err)}`);
}
void startGatewayMemoryBackend({ cfg: params.cfg, log: params.log }).catch((err) => {
params.log.warn(`qmd memory startup initialization failed: ${String(err)}`);
});
if (shouldWakeFromRestartSentinel()) {
setTimeout(() => {
void scheduleRestartSentinelWake({ deps: params.deps });