mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-28 05:16:23 -06:00
fix(config): cap legacy toolsBySender deprecation warning cache with shared dedupe helper (#101696)
* fix(config): use shared dedupe cache for legacy toolsBySender warnings
Replace unbounded Set with createDedupeCache({ ttlMs: 0, maxSize: 4096 })
from src/infra/dedupe.ts. The shared helper provides check() with
touch-on-read and max-size pruning — no custom LRU stack needed.
Tests verify eviction and hot-key retention through the public
resolveToolsBySender API without a testing-only cache export.
* test(config): tighten legacy warning cache proof
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// Verifies group-policy normalization and runtime resolution.
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "./config.js";
|
||||
import {
|
||||
resolveChannelGroupPolicy,
|
||||
@@ -412,4 +412,42 @@ describe("resolveToolsBySender", () => {
|
||||
expect(String(warningMessage)).toContain(`toolsBySender key "${legacyKey}"`);
|
||||
expect(warningMeta?.code).toBe("OPENCLAW_TOOLS_BY_SENDER_UNTYPED_KEY");
|
||||
});
|
||||
|
||||
describe("legacy key warning dedupe cache", () => {
|
||||
let resolveToolsBySenderFn: typeof resolveToolsBySender;
|
||||
|
||||
const resolveFreshConfig = (legacyKey: string) => {
|
||||
resolveToolsBySenderFn({
|
||||
toolsBySender: { [legacyKey]: { allow: ["read"] }, "*": { deny: ["exec"] } },
|
||||
senderId: "some-id",
|
||||
});
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.resetModules();
|
||||
const mod = await import("./group-policy.js");
|
||||
resolveToolsBySenderFn = mod.resolveToolsBySender;
|
||||
});
|
||||
|
||||
it("refreshes recent keys across config snapshots and re-warns evicted keys", () => {
|
||||
const warningSpy = vi.spyOn(process, "emitWarning").mockImplementation(() => undefined);
|
||||
|
||||
for (let i = 0; i < 4096; i++) {
|
||||
resolveFreshConfig(`legacy-key-${i}`);
|
||||
}
|
||||
expect(warningSpy).toHaveBeenCalledTimes(4096);
|
||||
|
||||
resolveFreshConfig("legacy-key-0");
|
||||
expect(warningSpy).toHaveBeenCalledTimes(4096);
|
||||
|
||||
resolveFreshConfig("overflow-key");
|
||||
expect(warningSpy).toHaveBeenCalledTimes(4097);
|
||||
|
||||
resolveFreshConfig("legacy-key-0");
|
||||
expect(warningSpy).toHaveBeenCalledTimes(4097);
|
||||
|
||||
resolveFreshConfig("legacy-key-1");
|
||||
expect(warningSpy).toHaveBeenCalledTimes(4098);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
normalizeOptionalString,
|
||||
} from "@openclaw/normalization-core/string-coerce";
|
||||
import type { ChannelId } from "../channels/plugins/channel-id.types.js";
|
||||
import { createDedupeCache } from "../infra/dedupe.js";
|
||||
import { resolveAccountEntry } from "../routing/account-lookup.js";
|
||||
import { normalizeAccountId } from "../routing/session-key.js";
|
||||
import { normalizeMessageChannel } from "../utils/message-channel-core.js";
|
||||
@@ -72,7 +73,12 @@ type CompiledSenderPolicy = {
|
||||
wildcard?: GroupToolPolicyConfig;
|
||||
};
|
||||
|
||||
const warnedLegacyToolsBySenderKeys = new Set<string>();
|
||||
const MAX_WARNED_LEGACY_TOOLS_BY_SENDER_KEYS = 4096;
|
||||
// Warning state spans fresh config snapshots; bounding it means evicted legacy keys can re-warn.
|
||||
const warnedLegacyToolsBySenderKeys = createDedupeCache({
|
||||
ttlMs: 0,
|
||||
maxSize: MAX_WARNED_LEGACY_TOOLS_BY_SENDER_KEYS,
|
||||
});
|
||||
const compiledToolsBySenderCache = new WeakMap<
|
||||
GroupToolPolicyBySenderConfig,
|
||||
CompiledSenderPolicy
|
||||
@@ -137,10 +143,9 @@ function normalizeLegacySenderKey(value: string): string {
|
||||
|
||||
function warnLegacyToolsBySenderKey(rawKey: string) {
|
||||
const trimmed = rawKey.trim();
|
||||
if (!trimmed || warnedLegacyToolsBySenderKeys.has(trimmed)) {
|
||||
if (!trimmed || warnedLegacyToolsBySenderKeys.check(trimmed)) {
|
||||
return;
|
||||
}
|
||||
warnedLegacyToolsBySenderKeys.add(trimmed);
|
||||
process.emitWarning(
|
||||
`toolsBySender key "${trimmed}" is deprecated. Use explicit prefixes (channel:, id:, e164:, username:, name:). Legacy unprefixed keys are matched as id only.`,
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user