mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 08:30:43 +00:00
Summary: - The PR changes Gateway reload planning, CLI plugin install-index writes, plugin runtime/cache cleanup, docs, changelog, and tests so plugin enable/disable hot reloads while install/update/uninstall stay restart-backed. - Reproducibility: yes. The earlier blocker has a source-level reproduction: run an external plugin install/up ... watches config and only the managed plugin index changes; the PR now tests that path and queues a restart. ClawSweeper fixups: - Included follow-up commit: fix: hot reload plugin management changes - Included follow-up commit: fix(clawsweeper): address review for automerge-openclaw-openclaw-7597… - Ran the ClawSweeper repair loop before final review. Validation: - ClawSweeper review passed for head860594f722. - Required merge gates passed before the squash merge. Prepared head SHA:860594f722Review: https://github.com/openclaw/openclaw/pull/75976#issuecomment-4363168379 Co-authored-by: Peter Steinberger <steipete@gmail.com> Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
59 lines
1.9 KiB
TypeScript
59 lines
1.9 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { PluginLoaderCacheState, PluginLoadReentryError } from "./loader-cache-state.js";
|
|
|
|
describe("PluginLoaderCacheState", () => {
|
|
it("evicts the least recently used registry cache entry", () => {
|
|
const cache = new PluginLoaderCacheState<string>(2);
|
|
|
|
cache.set("", "empty");
|
|
cache.set("a", "alpha");
|
|
cache.set("b", "bravo");
|
|
expect(cache.get("a")).toBe("alpha");
|
|
|
|
cache.set("c", "charlie");
|
|
|
|
expect(cache.get("b")).toBeUndefined();
|
|
expect(cache.get("a")).toBe("alpha");
|
|
expect(cache.get("c")).toBe("charlie");
|
|
});
|
|
|
|
it("tracks in-flight loads and reports reentry by cache key", () => {
|
|
const cache = new PluginLoaderCacheState<string>(2);
|
|
|
|
cache.beginLoad("demo");
|
|
expect(cache.isLoadInFlight("demo")).toBe(true);
|
|
expect(() => cache.beginLoad("demo")).toThrow(PluginLoadReentryError);
|
|
|
|
cache.finishLoad("demo");
|
|
expect(cache.isLoadInFlight("demo")).toBe(false);
|
|
});
|
|
|
|
it("clears registry, in-flight, and warning state together", () => {
|
|
const cache = new PluginLoaderCacheState<string>(2);
|
|
|
|
cache.set("demo", "registry");
|
|
cache.beginLoad("demo");
|
|
cache.recordOpenAllowlistWarning("demo-warning");
|
|
|
|
cache.clear();
|
|
|
|
expect(cache.get("demo")).toBeUndefined();
|
|
expect(cache.isLoadInFlight("demo")).toBe(false);
|
|
expect(cache.hasOpenAllowlistWarning("demo-warning")).toBe(false);
|
|
});
|
|
|
|
it("clears cached registries without dropping in-flight load guards", () => {
|
|
const cache = new PluginLoaderCacheState<string>(2);
|
|
|
|
cache.set("demo", "registry");
|
|
cache.beginLoad("demo");
|
|
cache.recordOpenAllowlistWarning("demo-warning");
|
|
|
|
cache.clearCachedRegistries();
|
|
|
|
expect(cache.get("demo")).toBeUndefined();
|
|
expect(cache.isLoadInFlight("demo")).toBe(true);
|
|
expect(cache.hasOpenAllowlistWarning("demo-warning")).toBe(false);
|
|
});
|
|
});
|