mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-02 18:55:17 +00:00
perf: avoid full session snapshots for entry reads
This commit is contained in:
@@ -59,6 +59,9 @@ describe("agent runner helpers", () => {
|
||||
});
|
||||
expect(shouldEmitResult()).toBe(true);
|
||||
expect(shouldEmitOutput()).toBe(true);
|
||||
expect(hoisted.loadSessionStoreMock).toHaveBeenCalledWith("/tmp/store.json", {
|
||||
clone: false,
|
||||
});
|
||||
});
|
||||
|
||||
it("caches session verbose reads briefly while still refreshing live changes", () => {
|
||||
|
||||
@@ -27,7 +27,7 @@ function readCurrentVerboseLevel(params: VerboseGateParams): VerboseLevel | unde
|
||||
return undefined;
|
||||
}
|
||||
try {
|
||||
const store = loadSessionStore(params.storePath);
|
||||
const store = loadSessionStore(params.storePath, { clone: false });
|
||||
const entry = store[params.sessionKey];
|
||||
return typeof entry?.verboseLevel === "string"
|
||||
? normalizeVerboseLevel(entry.verboseLevel)
|
||||
|
||||
@@ -444,6 +444,7 @@ describe("Session Store Cache", () => {
|
||||
|
||||
expect(readSessionUpdatedAt({ storePath, sessionKey: "agent:main:main" })).toBe(updatedAt);
|
||||
expect(parseSpy).not.toHaveBeenCalled();
|
||||
expect(getSessionStoreSnapshotCacheStatsForTest().entries).toBe(1);
|
||||
|
||||
parseSpy.mockRestore();
|
||||
});
|
||||
@@ -507,6 +508,33 @@ describe("Session Store Cache", () => {
|
||||
expect(readSessionStoreSnapshot(storePath)["session:1"].origin?.provider).toBe("openai");
|
||||
});
|
||||
|
||||
it("reads immutable single entries without populating whole-store snapshots", async () => {
|
||||
await saveSessionStore(storePath, {
|
||||
"session:1": createSessionEntry({
|
||||
sessionId: "id-1",
|
||||
skillsSnapshot: {
|
||||
prompt: "single entry prompt ".repeat(200),
|
||||
skills: [{ name: "alpha" }],
|
||||
},
|
||||
}),
|
||||
"session:2": createSessionEntry({ sessionId: "id-2" }),
|
||||
});
|
||||
clearSessionStoreCacheForTest();
|
||||
|
||||
const entry = readSessionEntry(storePath, "session:1");
|
||||
|
||||
expect(entry?.sessionId).toBe("id-1");
|
||||
expect(Object.isFrozen(entry)).toBe(true);
|
||||
expect(Object.isFrozen(entry?.skillsSnapshot?.skills)).toBe(true);
|
||||
expect(getSessionStoreSnapshotCacheStatsForTest().entries).toBe(0);
|
||||
|
||||
const cached = loadSessionStore(storePath, { clone: false });
|
||||
expect(() => {
|
||||
(entry as SessionEntry).displayName = "mutated returned entry";
|
||||
}).toThrow(TypeError);
|
||||
expect(cached["session:1"].displayName).toBe("Test Session 1");
|
||||
});
|
||||
|
||||
it("does not tag snapshots with stats from writes racing after a disk read", async () => {
|
||||
await saveSessionStore(
|
||||
storePath,
|
||||
|
||||
@@ -243,6 +243,10 @@ export function cloneSessionStoreSnapshot(
|
||||
return deepFreeze(cloned);
|
||||
}
|
||||
|
||||
export function cloneSessionStoreSnapshotEntry(entry: SessionEntry): SessionStoreSnapshotEntry {
|
||||
return deepFreeze(cloneSessionStoreRecord({ entry }).entry);
|
||||
}
|
||||
|
||||
export function getSessionStoreTtl(): number {
|
||||
return resolveCacheTtlMs({
|
||||
envValue: process.env.OPENCLAW_SESSION_CACHE_TTL_MS,
|
||||
|
||||
@@ -13,6 +13,7 @@ import { getFileStatSnapshot } from "../cache-utils.js";
|
||||
import { hydrateSessionStoreSkillPromptRefs } from "./skill-prompt-blobs.js";
|
||||
import {
|
||||
cloneSessionStoreRecord,
|
||||
cloneSessionStoreSnapshotEntry,
|
||||
cloneSessionStoreSnapshot,
|
||||
internSessionEntryLargeStrings,
|
||||
isSessionStoreCacheEnabled,
|
||||
@@ -488,12 +489,12 @@ export function readSessionEntry(
|
||||
storePath: string,
|
||||
sessionKey: string,
|
||||
): SessionStoreSnapshotEntry | undefined {
|
||||
const snapshot = readSessionStoreSnapshot(storePath);
|
||||
const store = loadSessionStore(storePath, { clone: false });
|
||||
const resolved = resolveSessionStoreEntry({
|
||||
store: snapshot as Record<string, SessionEntry>,
|
||||
store,
|
||||
sessionKey,
|
||||
});
|
||||
return resolved.existing as SessionStoreSnapshotEntry | undefined;
|
||||
return resolved.existing ? cloneSessionStoreSnapshotEntry(resolved.existing) : undefined;
|
||||
}
|
||||
|
||||
export function readSessionEntries(storePath: string): SessionStoreSnapshotEntries {
|
||||
|
||||
@@ -113,7 +113,8 @@ export function readSessionUpdatedAt(params: {
|
||||
sessionKey: string;
|
||||
}): number | undefined {
|
||||
try {
|
||||
return readSessionEntry(params.storePath, params.sessionKey)?.updatedAt;
|
||||
const store = loadSessionStore(params.storePath, { clone: false });
|
||||
return resolveSessionStoreEntry({ store, sessionKey: params.sessionKey }).existing?.updatedAt;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user