mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-21 10:16:44 +00:00
fix(gateway): hot reload auth cooldown changes
This commit is contained in:
@@ -97,9 +97,10 @@ const BASE_RELOAD_RULES: ReloadRule[] = [
|
||||
kind: "hot",
|
||||
actions: ["restart-heartbeat"],
|
||||
},
|
||||
// Auth cooldown readers resolve values from the active config for each auth
|
||||
// failure decision, so cooldown tuning does not need a gateway restart.
|
||||
{ prefix: "auth.cooldowns", kind: "none" },
|
||||
// Auth cooldown readers resolve values from the active runtime config for each
|
||||
// auth failure decision, so cooldown tuning needs a snapshot refresh but not
|
||||
// a gateway restart.
|
||||
{ prefix: "auth.cooldowns", kind: "hot" },
|
||||
{
|
||||
prefix: "agents.list",
|
||||
kind: "hot",
|
||||
|
||||
@@ -411,7 +411,7 @@ describe("buildGatewayReloadPlan", () => {
|
||||
expect(plan.noopPaths).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it("treats auth cooldown changes as no-op for gateway restart planning", () => {
|
||||
it("hot-reloads auth cooldown changes without a gateway restart", () => {
|
||||
const changedPaths = [
|
||||
"auth.cooldowns.billingBackoffHours",
|
||||
"auth.cooldowns.billingBackoffHoursByProvider.anthropic",
|
||||
@@ -420,9 +420,9 @@ describe("buildGatewayReloadPlan", () => {
|
||||
|
||||
expect(plan.restartGateway).toBe(false);
|
||||
expect(plan.restartReasons).toStrictEqual([]);
|
||||
expect(plan.hotReasons).toStrictEqual([]);
|
||||
expect(plan.noopPaths).toEqual(changedPaths);
|
||||
expect(resolveConfigReloadMetadata("auth.cooldowns.billingBackoffHours").kind).toBe("none");
|
||||
expect(plan.hotReasons).toStrictEqual(changedPaths);
|
||||
expect(plan.noopPaths).toStrictEqual([]);
|
||||
expect(resolveConfigReloadMetadata("auth.cooldowns.billingBackoffHours").kind).toBe("hot");
|
||||
});
|
||||
|
||||
it("restarts for gateway.auth.token changes", () => {
|
||||
@@ -481,7 +481,7 @@ describe("buildGatewayReloadPlan", () => {
|
||||
{
|
||||
path: "auth.cooldowns.billingBackoffHours",
|
||||
expectRestartGateway: false,
|
||||
expectNoopPath: "auth.cooldowns.billingBackoffHours",
|
||||
expectHotPath: "auth.cooldowns.billingBackoffHours",
|
||||
},
|
||||
{
|
||||
path: "gateway.auth.token",
|
||||
@@ -1353,6 +1353,57 @@ describe("startGatewayConfigReloader", () => {
|
||||
await harness.reloader.stop();
|
||||
});
|
||||
|
||||
it("keeps external auth cooldown writes on the hot reload path", async () => {
|
||||
const previousConfig: OpenClawConfig = {
|
||||
gateway: { reload: { debounceMs: 0 } },
|
||||
auth: {
|
||||
cooldowns: {
|
||||
billingBackoffHours: 1,
|
||||
billingBackoffHoursByProvider: { anthropic: 2 },
|
||||
},
|
||||
},
|
||||
};
|
||||
const nextConfig: OpenClawConfig = {
|
||||
gateway: { reload: { debounceMs: 0 } },
|
||||
auth: {
|
||||
cooldowns: {
|
||||
billingBackoffHours: 3,
|
||||
billingBackoffHoursByProvider: { anthropic: 4 },
|
||||
},
|
||||
},
|
||||
};
|
||||
const readSnapshot = vi.fn<() => Promise<ConfigFileSnapshot>>().mockResolvedValueOnce(
|
||||
makeSnapshot({
|
||||
sourceConfig: nextConfig,
|
||||
runtimeConfig: nextConfig,
|
||||
config: nextConfig,
|
||||
hash: "external-auth-cooldowns-1",
|
||||
}),
|
||||
);
|
||||
const harness = createReloaderHarness(readSnapshot, {
|
||||
initialCompareConfig: previousConfig,
|
||||
});
|
||||
|
||||
harness.watcher.emit("change");
|
||||
await vi.runOnlyPendingTimersAsync();
|
||||
|
||||
expect(harness.onRestart).not.toHaveBeenCalled();
|
||||
const [plan, hotConfig] = getOnlyHotReloadCall(harness);
|
||||
expect(plan.changedPaths).toEqual([
|
||||
"auth.cooldowns.billingBackoffHours",
|
||||
"auth.cooldowns.billingBackoffHoursByProvider.anthropic",
|
||||
]);
|
||||
expect(plan.restartGateway).toBe(false);
|
||||
expect(plan.hotReasons).toEqual([
|
||||
"auth.cooldowns.billingBackoffHours",
|
||||
"auth.cooldowns.billingBackoffHoursByProvider.anthropic",
|
||||
]);
|
||||
expect(plan.noopPaths).toStrictEqual([]);
|
||||
expect(hotConfig).toBe(nextConfig);
|
||||
|
||||
await harness.reloader.stop();
|
||||
});
|
||||
|
||||
it("queues restart when an external plugin source write also changes plugin config", async () => {
|
||||
const previousConfig: OpenClawConfig = {
|
||||
gateway: { reload: { debounceMs: 0 } },
|
||||
|
||||
Reference in New Issue
Block a user