mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-24 02:51:16 +00:00
fix(sessions): enforce maintenance cap ownership (#110241)
This commit is contained in:
@@ -1561,6 +1561,61 @@ describe("sqlite session normalization", () => {
|
||||
).toEqual(["agent:main:newer", "agent:main:newest"]);
|
||||
});
|
||||
|
||||
it("preserves an active SQLite cron entry when durable entries exceed maxEntries", async () => {
|
||||
vi.mocked(getRuntimeConfig).mockReturnValue({
|
||||
session: {
|
||||
maintenance: {
|
||||
mode: "enforce",
|
||||
pruneAfter: "365d",
|
||||
maxEntries: 1,
|
||||
},
|
||||
},
|
||||
});
|
||||
const env = { ...process.env, OPENCLAW_STATE_DIR: paths.stateDir };
|
||||
const scopeFor = (sessionKey: string) => ({
|
||||
agentId: "main",
|
||||
env,
|
||||
sessionKey,
|
||||
storePath: paths.sqlitePath,
|
||||
});
|
||||
const cronKey = "agent:main:cron:job-1";
|
||||
const cronEntry = {
|
||||
lifecycleRevision: "cron-revision-1",
|
||||
sessionId: "cron-session",
|
||||
updatedAt: Date.now(),
|
||||
};
|
||||
|
||||
for (const [sessionKey, sessionId] of [
|
||||
["agent:main:slack:channel:C1", "channel-session-1"],
|
||||
["agent:main:slack:channel:C2", "channel-session-2"],
|
||||
] as const) {
|
||||
await patchSqliteSessionEntry(
|
||||
scopeFor(sessionKey),
|
||||
() => ({ sessionId, updatedAt: Date.now() - 1 }),
|
||||
{
|
||||
fallbackEntry: { sessionId, updatedAt: Date.now() - 1 },
|
||||
replaceEntry: true,
|
||||
skipMaintenance: true,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
await patchSqliteSessionEntry(scopeFor(cronKey), () => cronEntry, {
|
||||
fallbackEntry: cronEntry,
|
||||
replaceEntry: true,
|
||||
});
|
||||
await patchSqliteSessionEntry(scopeFor(cronKey), () => ({
|
||||
model: "gpt-5.5",
|
||||
updatedAt: Date.now() + 1,
|
||||
}));
|
||||
|
||||
expect(loadSqliteSessionEntry(scopeFor(cronKey))).toMatchObject({
|
||||
lifecycleRevision: "cron-revision-1",
|
||||
model: "gpt-5.5",
|
||||
sessionId: "cron-session",
|
||||
});
|
||||
});
|
||||
|
||||
it("evicts old SQLite transcript rows only when no remaining entry references them", async () => {
|
||||
vi.mocked(getRuntimeConfig).mockReturnValue({
|
||||
session: {
|
||||
|
||||
@@ -531,14 +531,13 @@ function wouldCapActiveSession(params: {
|
||||
*/
|
||||
export function capEntryCount(
|
||||
store: Record<string, SessionEntry>,
|
||||
overrideMax?: number,
|
||||
maxEntries: number,
|
||||
opts: {
|
||||
log?: boolean;
|
||||
onCapped?: (params: { key: string; entry: SessionEntry }) => void;
|
||||
preserveKeys?: ReadonlySet<string>;
|
||||
} = {},
|
||||
): number {
|
||||
const maxEntries = overrideMax ?? resolveMaintenanceConfigFromInput().maxEntries;
|
||||
const preservedCount = Object.entries(store).filter(([key, entry]) =>
|
||||
shouldPreserveMaintenanceEntry({ key, entry, preserveKeys: opts.preserveKeys }),
|
||||
).length;
|
||||
|
||||
@@ -1483,6 +1483,37 @@ describe("Integration: saveSessionStore with pruning", () => {
|
||||
expect(loaded).toHaveProperty("session-50");
|
||||
});
|
||||
|
||||
it("updateSessionStore honors configured maxEntries without an explicit override", async () => {
|
||||
const now = Date.now();
|
||||
await fs.writeFile(
|
||||
storePath,
|
||||
JSON.stringify({
|
||||
oldest: makeEntry(now - 2),
|
||||
recent: makeEntry(now - 1),
|
||||
}),
|
||||
"utf-8",
|
||||
);
|
||||
mockLoadConfig.mockReturnValue({
|
||||
session: {
|
||||
maintenance: {
|
||||
mode: "enforce",
|
||||
pruneAfter: "365d",
|
||||
maxEntries: 2,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await updateSessionStore(storePath, (store) => {
|
||||
store.newest = makeEntry(now);
|
||||
});
|
||||
|
||||
const loaded = loadSessionStore(storePath, { skipCache: true });
|
||||
expect(Object.keys(loaded)).toHaveLength(2);
|
||||
expect(loaded).toHaveProperty("newest");
|
||||
expect(loaded).toHaveProperty("recent");
|
||||
expect(loaded.oldest).toBeUndefined();
|
||||
});
|
||||
|
||||
it("loadSessionStore honors configured maxEntries without an explicit override", async () => {
|
||||
mockLoadConfig.mockReturnValue({
|
||||
session: {
|
||||
|
||||
Reference in New Issue
Block a user