mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-03 14:44:05 +00:00
fix(signal): bound api mode cache clocks
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { describe, expect, it, vi, beforeEach } from "vitest";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
signalRpcRequest as signalRpcRequestImpl,
|
||||
detectSignalApiMode,
|
||||
@@ -37,6 +37,11 @@ beforeEach(() => {
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
function setApiMode(mode: SignalApiMode) {
|
||||
currentApiMode = mode;
|
||||
}
|
||||
@@ -378,6 +383,44 @@ describe("signalCheck", () => {
|
||||
error: "Signal API not reachable at http://localhost:8080",
|
||||
});
|
||||
});
|
||||
|
||||
it("drops cached auto mode when the current clock is not a valid date timestamp", async () => {
|
||||
setApiMode("auto");
|
||||
vi.spyOn(Date, "now").mockReturnValueOnce(1_700_000_000_000).mockReturnValueOnce(Number.NaN);
|
||||
mockNativeCheck.mockResolvedValue({ ok: true, status: 200 });
|
||||
mockContainerCheck.mockResolvedValue({ ok: false, status: 404 });
|
||||
|
||||
await expect(signalCheck("http://auto-invalid-clock.local:8080")).resolves.toEqual({
|
||||
ok: true,
|
||||
status: 200,
|
||||
});
|
||||
await expect(signalCheck("http://auto-invalid-clock.local:8080")).resolves.toEqual({
|
||||
ok: true,
|
||||
status: 200,
|
||||
});
|
||||
|
||||
expect(mockNativeCheck).toHaveBeenCalledTimes(4);
|
||||
expect(mockContainerCheck).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("does not cache auto mode when the expiry timestamp would exceed the valid date range", async () => {
|
||||
setApiMode("auto");
|
||||
vi.spyOn(Date, "now").mockReturnValue(8_640_000_000_000_000);
|
||||
mockNativeCheck.mockResolvedValue({ ok: true, status: 200 });
|
||||
mockContainerCheck.mockResolvedValue({ ok: false, status: 404 });
|
||||
|
||||
await expect(signalCheck("http://auto-overflow-clock.local:8080")).resolves.toEqual({
|
||||
ok: true,
|
||||
status: 200,
|
||||
});
|
||||
await expect(signalCheck("http://auto-overflow-clock.local:8080")).resolves.toEqual({
|
||||
ok: true,
|
||||
status: 200,
|
||||
});
|
||||
|
||||
expect(mockNativeCheck).toHaveBeenCalledTimes(4);
|
||||
expect(mockContainerCheck).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("streamSignalEvents", () => {
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
* only need to change their import path.
|
||||
*/
|
||||
|
||||
import {
|
||||
asDateTimestampMs,
|
||||
resolveExpiresAtMsFromDurationMs,
|
||||
} from "openclaw/plugin-sdk/number-runtime";
|
||||
import {
|
||||
containerCheck,
|
||||
containerRpcRequest,
|
||||
@@ -74,24 +78,33 @@ async function resolveAutoApiMode(
|
||||
timeoutMs = DEFAULT_TIMEOUT_MS,
|
||||
options: { account?: string; requireContainerReceive?: boolean } = {},
|
||||
): Promise<"native" | "container"> {
|
||||
const rawNow = Date.now();
|
||||
const now = asDateTimestampMs(rawNow);
|
||||
const cached = detectedModeCache.get(baseUrl);
|
||||
if (cached && cached.expiresAt > Date.now()) {
|
||||
if (
|
||||
cached.mode !== "container" ||
|
||||
!options.requireContainerReceive ||
|
||||
(Boolean(options.account?.trim()) && cached.receiveAccount === options.account?.trim())
|
||||
) {
|
||||
return cached.mode;
|
||||
if (cached) {
|
||||
if (now !== undefined && cached.expiresAt > now) {
|
||||
if (
|
||||
cached.mode !== "container" ||
|
||||
!options.requireContainerReceive ||
|
||||
(Boolean(options.account?.trim()) && cached.receiveAccount === options.account?.trim())
|
||||
) {
|
||||
return cached.mode;
|
||||
}
|
||||
} else {
|
||||
detectedModeCache.delete(baseUrl);
|
||||
}
|
||||
}
|
||||
const detected = await detectSignalApiMode(baseUrl, timeoutMs, options);
|
||||
detectedModeCache.set(baseUrl, {
|
||||
mode: detected,
|
||||
expiresAt: Date.now() + MODE_CACHE_TTL_MS,
|
||||
...(detected === "container" && options.requireContainerReceive && options.account
|
||||
? { receiveAccount: options.account }
|
||||
: {}),
|
||||
});
|
||||
const expiresAt = resolveExpiresAtMsFromDurationMs(MODE_CACHE_TTL_MS, { nowMs: rawNow });
|
||||
if (expiresAt !== undefined) {
|
||||
detectedModeCache.set(baseUrl, {
|
||||
mode: detected,
|
||||
expiresAt,
|
||||
...(detected === "container" && options.requireContainerReceive && options.account
|
||||
? { receiveAccount: options.account }
|
||||
: {}),
|
||||
});
|
||||
}
|
||||
return detected;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user