Skip to content

Commit d937944

Browse files
author
ai-hpc
committed
perf(config): avoid stale implicit auto-enable cache
1 parent 638b1e8 commit d937944

2 files changed

Lines changed: 49 additions & 15 deletions

File tree

src/config/plugin-auto-enable.apply.ts

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ import type {
1212
import { hashRuntimeConfigValue } from "./runtime-snapshot.js";
1313
import type { OpenClawConfig } from "./types.openclaw.js";
1414

15-
const ABSENT_PLUGIN_AUTO_ENABLE_INPUT = {};
16-
1715
type PluginAutoEnableCacheEntry = {
1816
configFingerprint: string;
1917
envFingerprint: string;
@@ -54,10 +52,6 @@ function getOrCreateWeakMap<K extends object, V>(
5452
return next;
5553
}
5654

57-
function resolveInputIdentityKey(value: object | undefined): object {
58-
return value ?? ABSENT_PLUGIN_AUTO_ENABLE_INPUT;
59-
}
60-
6155
function stableFingerprintValue(value: unknown): string {
6256
if (value === null || typeof value !== "object") {
6357
return JSON.stringify(value) ?? "null";
@@ -133,10 +127,8 @@ export function applyPluginAutoEnable(params: {
133127
discovery?: PluginDiscoveryResult;
134128
}): PluginAutoEnableResult {
135129
const config = params.config;
136-
if (config && typeof config === "object") {
130+
if (config && typeof config === "object" && params.manifestRegistry && params.discovery) {
137131
const env = params.env ?? process.env;
138-
const manifestRegistry = resolveInputIdentityKey(params.manifestRegistry);
139-
const discovery = resolveInputIdentityKey(params.discovery);
140132
const envCache = getOrCreateWeakMap(
141133
(sameTurnApplyCache ??= new WeakMap()),
142134
config,
@@ -149,10 +141,10 @@ export function applyPluginAutoEnable(params: {
149141
);
150142
const discoveryCache = getOrCreateWeakMap(
151143
registryCache,
152-
manifestRegistry,
144+
params.manifestRegistry,
153145
() => new WeakMap<object, PluginAutoEnableCacheEntry>(),
154146
);
155-
const cached = discoveryCache.get(discovery);
147+
const cached = discoveryCache.get(params.discovery);
156148
if (cached && isPluginAutoEnableCacheEntryFresh({ entry: cached, config, env })) {
157149
return cached.result;
158150
}
@@ -163,7 +155,7 @@ export function applyPluginAutoEnable(params: {
163155
env: params.env,
164156
manifestRegistry: params.manifestRegistry,
165157
});
166-
discoveryCache.set(discovery, createPluginAutoEnableCacheEntry({ config, env, result }));
158+
discoveryCache.set(params.discovery, createPluginAutoEnableCacheEntry({ config, env, result }));
167159
scheduleSameTurnApplyCacheClear();
168160
return result;
169161
}

src/config/plugin-auto-enable.core.test.ts

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import fs from "node:fs";
22
import path from "node:path";
33
import { afterAll, afterEach, describe, expect, it, vi } from "vitest";
44
import { setCurrentPluginMetadataSnapshot } from "../plugins/current-plugin-metadata-snapshot.js";
5+
import type { PluginDiscoveryResult } from "../plugins/discovery.js";
56
import { resolveInstalledPluginIndexPolicyHash } from "../plugins/installed-plugin-index-policy.js";
67
import type { PluginManifestRegistry } from "../plugins/manifest-registry.js";
78
import type { PluginMetadataSnapshot } from "../plugins/plugin-metadata-snapshot.js";
@@ -61,6 +62,7 @@ vi.mock("../plugins/setup-registry.js", () => ({
6162
}));
6263

6364
const env = makeIsolatedEnv();
65+
const emptyDiscovery: PluginDiscoveryResult = { candidates: [], diagnostics: [] };
6466

6567
function createPluginMetadataSnapshot(params: {
6668
config?: OpenClawConfig;
@@ -1029,6 +1031,7 @@ describe("applyPluginAutoEnable core", () => {
10291031

10301032
it("reuses same-turn auto-enable results for identical fanout inputs", async () => {
10311033
setupRegistryMock.resolvePluginSetupAutoEnableReasons.mockClear();
1034+
const manifestRegistry = makeRegistry([{ id: "browser", channels: [] }]);
10321035
const config: OpenClawConfig = {
10331036
plugins: {
10341037
entries: {
@@ -1039,22 +1042,61 @@ describe("applyPluginAutoEnable core", () => {
10391042
},
10401043
};
10411044

1042-
const first = applyPluginAutoEnable({ config, env });
1043-
const second = applyPluginAutoEnable({ config, env });
1045+
const first = applyPluginAutoEnable({
1046+
config,
1047+
discovery: emptyDiscovery,
1048+
env,
1049+
manifestRegistry,
1050+
});
1051+
const second = applyPluginAutoEnable({
1052+
config,
1053+
discovery: emptyDiscovery,
1054+
env,
1055+
manifestRegistry,
1056+
});
10441057

10451058
expect(second).toBe(first);
10461059
expect(setupRegistryMock.resolvePluginSetupAutoEnableReasons).toHaveBeenCalledTimes(1);
10471060

10481061
await new Promise<void>((resolve) => {
10491062
setImmediate(resolve);
10501063
});
1051-
const third = applyPluginAutoEnable({ config, env });
1064+
const third = applyPluginAutoEnable({
1065+
config,
1066+
discovery: emptyDiscovery,
1067+
env,
1068+
manifestRegistry,
1069+
});
10521070

10531071
expect(third).not.toBe(first);
10541072
expect(third).toEqual(first);
10551073
expect(setupRegistryMock.resolvePluginSetupAutoEnableReasons).toHaveBeenCalledTimes(2);
10561074
});
10571075

1076+
it("does not reuse same-turn results for omitted metadata after current snapshot replacement", () => {
1077+
const config: OpenClawConfig = {
1078+
channels: { apn: { someKey: "value" } },
1079+
};
1080+
const firstRegistry = makeRegistry([{ id: "apn-one", channels: ["apn"] }]);
1081+
const secondRegistry = makeRegistry([{ id: "apn-two", channels: ["apn"] }]);
1082+
setCurrentPluginMetadataSnapshot(
1083+
createPluginMetadataSnapshot({ config, manifestRegistry: firstRegistry }),
1084+
{ config, env },
1085+
);
1086+
1087+
const first = applyPluginAutoEnable({ config, env });
1088+
setCurrentPluginMetadataSnapshot(
1089+
createPluginMetadataSnapshot({ config, manifestRegistry: secondRegistry }),
1090+
{ config, env },
1091+
);
1092+
const second = applyPluginAutoEnable({ config, env });
1093+
1094+
expect(first.config.plugins?.entries?.["apn-one"]?.enabled).toBe(true);
1095+
expect(second.config.plugins?.entries?.["apn-two"]?.enabled).toBe(true);
1096+
expect(second.config.plugins?.entries?.["apn-one"]).toBeUndefined();
1097+
expect(second).not.toBe(first);
1098+
});
1099+
10581100
it("does not reuse same-turn auto-enable results across registry or env inputs", () => {
10591101
const channelConfig: OpenClawConfig = {
10601102
channels: { apn: { someKey: "value" } },

0 commit comments

Comments
 (0)