mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-03 17:44:06 +00:00
fix(active-memory): bound recall cache clocks
This commit is contained in:
@@ -4130,6 +4130,50 @@ describe("active-memory plugin", () => {
|
||||
expect(cached?.summary).toBe("memory 1");
|
||||
});
|
||||
|
||||
it("drops cached active-memory results when the current clock is not a valid date timestamp", () => {
|
||||
const nowSpy = vi.spyOn(Date, "now").mockReturnValue(1_700_000_000_000);
|
||||
const cacheKey = testing.buildCacheKey({
|
||||
agentId: "main",
|
||||
sessionKey: "agent:main:invalid-clock-cache",
|
||||
query: "cache invalid clock prompt",
|
||||
});
|
||||
testing.setCachedResult(
|
||||
cacheKey,
|
||||
{
|
||||
status: "ok",
|
||||
elapsedMs: 1,
|
||||
rawReply: "memory",
|
||||
summary: "memory",
|
||||
},
|
||||
15_000,
|
||||
);
|
||||
|
||||
nowSpy.mockReturnValue(Number.NaN);
|
||||
|
||||
expect(testing.getCachedResult(cacheKey)).toBeUndefined();
|
||||
});
|
||||
|
||||
it("does not cache active-memory results when the expiry timestamp would exceed the valid date range", () => {
|
||||
vi.spyOn(Date, "now").mockReturnValue(8_640_000_000_000_000);
|
||||
const cacheKey = testing.buildCacheKey({
|
||||
agentId: "main",
|
||||
sessionKey: "agent:main:overflow-cache",
|
||||
query: "cache overflow prompt",
|
||||
});
|
||||
testing.setCachedResult(
|
||||
cacheKey,
|
||||
{
|
||||
status: "ok",
|
||||
elapsedMs: 1,
|
||||
rawReply: "memory",
|
||||
summary: "memory",
|
||||
},
|
||||
15_000,
|
||||
);
|
||||
|
||||
expect(testing.getCachedResult(cacheKey)).toBeUndefined();
|
||||
});
|
||||
|
||||
it("skips recall after consecutive timeouts when circuit breaker trips (#74054)", async () => {
|
||||
const CONFIGURED_TIMEOUT_MS = 25;
|
||||
testing.setMinimumTimeoutMsForTests(1);
|
||||
|
||||
@@ -13,7 +13,11 @@ import {
|
||||
} from "openclaw/plugin-sdk/agent-runtime";
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
|
||||
import { closeActiveMemorySearchManager } from "openclaw/plugin-sdk/memory-host-search";
|
||||
import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
|
||||
import {
|
||||
asDateTimestampMs,
|
||||
parseStrictPositiveInteger,
|
||||
resolveExpiresAtMsFromDurationMs,
|
||||
} from "openclaw/plugin-sdk/number-runtime";
|
||||
import {
|
||||
resolveLivePluginConfigObject,
|
||||
resolvePluginConfigObject,
|
||||
@@ -1360,7 +1364,12 @@ function getCachedResult(cacheKey: string): ActiveRecallResult | undefined {
|
||||
if (!cached) {
|
||||
return undefined;
|
||||
}
|
||||
if (cached.expiresAt <= Date.now()) {
|
||||
const now = asDateTimestampMs(Date.now());
|
||||
if (
|
||||
now === undefined ||
|
||||
asDateTimestampMs(cached.expiresAt) === undefined ||
|
||||
cached.expiresAt <= now
|
||||
) {
|
||||
activeRecallCache.delete(cacheKey);
|
||||
return undefined;
|
||||
}
|
||||
@@ -1368,19 +1377,27 @@ function getCachedResult(cacheKey: string): ActiveRecallResult | undefined {
|
||||
}
|
||||
|
||||
function setCachedResult(cacheKey: string, result: ActiveRecallResult, ttlMs: number): void {
|
||||
const now = Date.now();
|
||||
const rawNow = Date.now();
|
||||
const now = asDateTimestampMs(rawNow);
|
||||
if (
|
||||
activeRecallCache.size >= DEFAULT_MAX_CACHE_ENTRIES ||
|
||||
now - lastActiveRecallCacheSweepAt >= CACHE_SWEEP_INTERVAL_MS
|
||||
(now !== undefined && now - lastActiveRecallCacheSweepAt >= CACHE_SWEEP_INTERVAL_MS)
|
||||
) {
|
||||
sweepExpiredCacheEntries(now);
|
||||
lastActiveRecallCacheSweepAt = now;
|
||||
if (now !== undefined) {
|
||||
lastActiveRecallCacheSweepAt = now;
|
||||
}
|
||||
}
|
||||
const expiresAt = resolveExpiresAtMsFromDurationMs(ttlMs, { nowMs: rawNow });
|
||||
if (expiresAt === undefined) {
|
||||
activeRecallCache.delete(cacheKey);
|
||||
return;
|
||||
}
|
||||
if (activeRecallCache.has(cacheKey)) {
|
||||
activeRecallCache.delete(cacheKey);
|
||||
}
|
||||
activeRecallCache.set(cacheKey, {
|
||||
expiresAt: now + ttlMs,
|
||||
expiresAt,
|
||||
result,
|
||||
});
|
||||
while (activeRecallCache.size > DEFAULT_MAX_CACHE_ENTRIES) {
|
||||
@@ -1392,9 +1409,13 @@ function setCachedResult(cacheKey: string, result: ActiveRecallResult, ttlMs: nu
|
||||
}
|
||||
}
|
||||
|
||||
function sweepExpiredCacheEntries(now = Date.now()): void {
|
||||
function sweepExpiredCacheEntries(now = asDateTimestampMs(Date.now())): void {
|
||||
if (now === undefined) {
|
||||
activeRecallCache.clear();
|
||||
return;
|
||||
}
|
||||
for (const [cacheKey, cached] of activeRecallCache.entries()) {
|
||||
if (cached.expiresAt <= now) {
|
||||
if (asDateTimestampMs(cached.expiresAt) === undefined || cached.expiresAt <= now) {
|
||||
activeRecallCache.delete(cacheKey);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user