mirror of
https://github.com/openclaw/openclaw.git
synced 2026-10-03 01:29:56 +00:00
fix(gateway): reduce session group discovery CPU overhead (#147909)
This commit is contained in:
parent
b5b7ca44ac
commit
15f63bf749
2 changed files with 89 additions and 1 deletions
|
|
@ -1,7 +1,8 @@
|
|||
import fs from "node:fs";
|
||||
import { performance } from "node:perf_hooks";
|
||||
import { DatabaseSync } from "node:sqlite";
|
||||
import { expect, test, vi } from "vitest";
|
||||
import { upsertSessionEntryCore } from "../config/sessions/session-accessor.js";
|
||||
import { loadSessionEntry, upsertSessionEntryCore } from "../config/sessions/session-accessor.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import * as sqliteIntegrity from "../infra/sqlite-integrity.js";
|
||||
import * as sqliteWal from "../infra/sqlite-wal.js";
|
||||
|
|
@ -9,6 +10,7 @@ import * as agentDatabaseLeases from "../state/openclaw-agent-db-lease.js";
|
|||
import {
|
||||
closeOpenClawAgentDatabasesForTest,
|
||||
listOpenClawAgentDatabasesForTest,
|
||||
openOpenClawAgentDatabase,
|
||||
} from "../state/openclaw-agent-db.js";
|
||||
import { closeOpenClawStateDatabaseForTest } from "../state/openclaw-state-db.js";
|
||||
import { setStateDirEnv, withStateDirEnv } from "../test-helpers/state-dir-env.js";
|
||||
|
|
@ -16,6 +18,89 @@ import { resolveSessionGroupMutationTargetsByName } from "./session-groups.js";
|
|||
|
||||
const EXPECTED_OPEN_HANDLE_CAP = 64;
|
||||
|
||||
test.each([false, true])(
|
||||
"discovers current group members without decoding saved prompts (cold=%s)",
|
||||
async (cold) => {
|
||||
await withStateDirEnv("openclaw-session-group-metadata-", async ({ stateDir }) => {
|
||||
setStateDirEnv(fs.realpathSync(stateDir));
|
||||
const scopes = [
|
||||
{ agentId: "main", sessionKey: "agent:main:group-member" },
|
||||
{ agentId: "research", sessionKey: "agent:research:matrix:group:!Room:example.org" },
|
||||
] as const;
|
||||
const config = {
|
||||
agents: { list: [{ id: "main", default: true }, { id: "research" }] },
|
||||
} satisfies OpenClawConfig;
|
||||
const entry = {
|
||||
sessionId: "group-member",
|
||||
updatedAt: 1,
|
||||
category: " Shared work ",
|
||||
skillsSnapshot: { prompt: "unneeded-group-prompt".repeat(4096), skills: [] },
|
||||
systemPromptReport: {
|
||||
source: "run" as const,
|
||||
generatedAt: 1,
|
||||
systemPrompt: { chars: 1, projectContextChars: 0, nonProjectContextChars: 1 },
|
||||
injectedWorkspaceFiles: [],
|
||||
skills: { promptChars: 0, entries: [] },
|
||||
tools: { listChars: 0, schemaChars: 0, entries: [] },
|
||||
},
|
||||
};
|
||||
const parse = vi.spyOn(JSON, "parse");
|
||||
const readTargets = () => {
|
||||
parse.mockClear();
|
||||
const targets = resolveSessionGroupMutationTargetsByName(config);
|
||||
expect(
|
||||
parse.mock.calls.filter(
|
||||
([json]) => json.includes('"skillsSnapshot"') || json.includes('"systemPromptReport"'),
|
||||
),
|
||||
).toEqual([]);
|
||||
return targets;
|
||||
};
|
||||
try {
|
||||
for (const scope of scopes) {
|
||||
await upsertSessionEntryCore(scope, entry);
|
||||
}
|
||||
if (cold) {
|
||||
closeOpenClawAgentDatabasesForTest();
|
||||
}
|
||||
expect(readTargets()).toEqual(new Map([["Shared work", scopes]]));
|
||||
await upsertSessionEntryCore(scopes[0], { ...entry, category: "Renamed" });
|
||||
expect(readTargets()).toEqual(
|
||||
new Map([
|
||||
["Renamed", [scopes[0]]],
|
||||
["Shared work", [scopes[1]]],
|
||||
]),
|
||||
);
|
||||
const database = openOpenClawAgentDatabase(scopes[0]);
|
||||
const external = new DatabaseSync(database.path);
|
||||
try {
|
||||
external
|
||||
.prepare(
|
||||
"UPDATE session_nodes SET entry_json = json_set(entry_json, '$.category', ?) WHERE session_key = ?",
|
||||
)
|
||||
.run("External", scopes[0].sessionKey);
|
||||
} finally {
|
||||
external.close();
|
||||
}
|
||||
expect(readTargets()).toEqual(
|
||||
new Map([
|
||||
["External", [scopes[0]]],
|
||||
["Shared work", [scopes[1]]],
|
||||
]),
|
||||
);
|
||||
parse.mockRestore();
|
||||
expect(loadSessionEntry(scopes[0])).toMatchObject({
|
||||
skillsSnapshot: entry.skillsSnapshot,
|
||||
systemPromptReport: entry.systemPromptReport,
|
||||
});
|
||||
} finally {
|
||||
parse.mockRestore();
|
||||
closeOpenClawAgentDatabasesForTest();
|
||||
closeOpenClawStateDatabaseForTest();
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test("discovers groups across more than the handle cap without writable database maintenance", async () => {
|
||||
await withStateDirEnv("openclaw-session-group-readonly-", async ({ stateDir }) => {
|
||||
setStateDirEnv(fs.realpathSync(stateDir));
|
||||
|
|
|
|||
|
|
@ -450,6 +450,9 @@ export function resolveSessionGroupMutationTargetsByName(
|
|||
for (const { sessionKey, entry } of listSessionEntriesReadOnly({
|
||||
agentId: storeTarget.agentId,
|
||||
storePath: storeTarget.storePath,
|
||||
// Membership only borrows category metadata; full reads decode every saved prompt.
|
||||
projection: "list",
|
||||
clone: false,
|
||||
})) {
|
||||
const groupName = normalizeOptionalString(entry.category);
|
||||
if (!groupName) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue