mirror of https://github.com/openclaw/openclaw.git
fix: address session-store cache review feedback
This commit is contained in:
parent
1212328c8d
commit
175c770171
|
|
@ -18,17 +18,18 @@ export function isCacheEnabled(ttlMs: number): boolean {
|
|||
return ttlMs > 0;
|
||||
}
|
||||
|
||||
export function getFileMtimeMs(filePath: string): number | undefined {
|
||||
try {
|
||||
return fs.statSync(filePath).mtimeMs;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
export type FileStatSnapshot = {
|
||||
mtimeMs: number;
|
||||
sizeBytes: number;
|
||||
};
|
||||
|
||||
export function getFileSizeBytes(filePath: string): number | undefined {
|
||||
export function getFileStatSnapshot(filePath: string): FileStatSnapshot | undefined {
|
||||
try {
|
||||
return fs.statSync(filePath).size;
|
||||
const stats = fs.statSync(filePath);
|
||||
return {
|
||||
mtimeMs: stats.mtimeMs,
|
||||
sizeBytes: stats.size,
|
||||
};
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -220,12 +220,12 @@ describe("Session Store Cache", () => {
|
|||
"session:1": createSessionEntry({ sessionId: "id-1", displayName: "Original" }),
|
||||
"session:2": createSessionEntry({ sessionId: "id-2", displayName: "Added" }),
|
||||
};
|
||||
const preWriteStat = fs.statSync(storePath);
|
||||
const json2 = JSON.stringify(store2, null, 2);
|
||||
fs.writeFileSync(storePath, json2);
|
||||
|
||||
// Force mtime to match the cached value so only size differs
|
||||
const stat = fs.statSync(storePath);
|
||||
fs.utimesSync(storePath, stat.atime, stat.mtime);
|
||||
fs.utimesSync(storePath, preWriteStat.atime, preWriteStat.mtime);
|
||||
|
||||
// The cache should detect the size change and reload from disk
|
||||
const loaded2 = loadSessionStore(storePath);
|
||||
|
|
|
|||
|
|
@ -17,12 +17,7 @@ import {
|
|||
normalizeSessionDeliveryFields,
|
||||
type DeliveryContext,
|
||||
} from "../../utils/delivery-context.js";
|
||||
import {
|
||||
getFileMtimeMs,
|
||||
getFileSizeBytes,
|
||||
isCacheEnabled,
|
||||
resolveCacheTtlMs,
|
||||
} from "../cache-utils.js";
|
||||
import { getFileStatSnapshot, isCacheEnabled, resolveCacheTtlMs } from "../cache-utils.js";
|
||||
import { loadConfig } from "../config.js";
|
||||
import type { SessionMaintenanceConfig, SessionMaintenanceMode } from "../types.base.js";
|
||||
import { enforceSessionDiskBudget, type SessionDiskBudgetSweepResult } from "./disk-budget.js";
|
||||
|
|
@ -213,9 +208,11 @@ export function loadSessionStore(
|
|||
if (!opts.skipCache && isSessionStoreCacheEnabled()) {
|
||||
const cached = SESSION_STORE_CACHE.get(storePath);
|
||||
if (cached && isSessionStoreCacheValid(cached)) {
|
||||
const currentMtimeMs = getFileMtimeMs(storePath);
|
||||
const currentSizeBytes = getFileSizeBytes(storePath);
|
||||
if (currentMtimeMs === cached.mtimeMs && currentSizeBytes === cached.sizeBytes) {
|
||||
const currentFileStat = getFileStatSnapshot(storePath);
|
||||
if (
|
||||
currentFileStat?.mtimeMs === cached.mtimeMs &&
|
||||
currentFileStat?.sizeBytes === cached.sizeBytes
|
||||
) {
|
||||
// Return a deep copy to prevent external mutations affecting cache
|
||||
return structuredClone(cached.store);
|
||||
}
|
||||
|
|
@ -230,7 +227,8 @@ export function loadSessionStore(
|
|||
// A short synchronous backoff (50 ms via `Atomics.wait`) is enough for the
|
||||
// writer to finish.
|
||||
let store: Record<string, SessionEntry> = {};
|
||||
let mtimeMs = getFileMtimeMs(storePath);
|
||||
let fileStat = getFileStatSnapshot(storePath);
|
||||
let mtimeMs = fileStat?.mtimeMs;
|
||||
let serializedFromDisk: string | undefined;
|
||||
const maxReadAttempts = process.platform === "win32" ? 3 : 1;
|
||||
const retryBuf = maxReadAttempts > 1 ? new Int32Array(new SharedArrayBuffer(4)) : undefined;
|
||||
|
|
@ -247,7 +245,8 @@ export function loadSessionStore(
|
|||
store = parsed;
|
||||
serializedFromDisk = raw;
|
||||
}
|
||||
mtimeMs = getFileMtimeMs(storePath) ?? mtimeMs;
|
||||
fileStat = getFileStatSnapshot(storePath) ?? fileStat;
|
||||
mtimeMs = fileStat?.mtimeMs;
|
||||
break;
|
||||
} catch {
|
||||
// File missing, locked, or transiently corrupt — retry on Windows.
|
||||
|
|
@ -295,7 +294,7 @@ export function loadSessionStore(
|
|||
loadedAt: Date.now(),
|
||||
storePath,
|
||||
mtimeMs,
|
||||
sizeBytes: getFileSizeBytes(storePath),
|
||||
sizeBytes: fileStat?.sizeBytes,
|
||||
serialized: serializedFromDisk,
|
||||
});
|
||||
}
|
||||
|
|
@ -664,7 +663,7 @@ function updateSessionStoreWriteCaches(params: {
|
|||
store: Record<string, SessionEntry>;
|
||||
serialized: string;
|
||||
}): void {
|
||||
const mtimeMs = getFileMtimeMs(params.storePath);
|
||||
const fileStat = getFileStatSnapshot(params.storePath);
|
||||
SESSION_STORE_SERIALIZED_CACHE.set(params.storePath, params.serialized);
|
||||
if (!isSessionStoreCacheEnabled()) {
|
||||
SESSION_STORE_CACHE.delete(params.storePath);
|
||||
|
|
@ -674,8 +673,8 @@ function updateSessionStoreWriteCaches(params: {
|
|||
store: structuredClone(params.store),
|
||||
loadedAt: Date.now(),
|
||||
storePath: params.storePath,
|
||||
mtimeMs,
|
||||
sizeBytes: getFileSizeBytes(params.storePath),
|
||||
mtimeMs: fileStat?.mtimeMs,
|
||||
sizeBytes: fileStat?.sizeBytes,
|
||||
serialized: params.serialized,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue