refactor(gateway): share no-op reload plan check (#113610)

This commit is contained in:
Vincent Koc
2026-07-25 18:45:12 +08:00
committed by GitHub
parent 1e04925e03
commit b8bb08a1ad
4 changed files with 23 additions and 35 deletions
+16
View File
@@ -34,6 +34,22 @@ export type GatewayReloadPlan = {
noopPaths: string[];
};
export function isNoopGatewayReloadPlan(plan: GatewayReloadPlan): boolean {
return (
!plan.restartGateway &&
plan.hotReasons.length === 0 &&
!plan.reloadHooks &&
!plan.restartGmailWatcher &&
!plan.restartCron &&
!plan.restartHeartbeat &&
!plan.restartHealthMonitor &&
!plan.reloadPlugins &&
!plan.disposeMcpRuntimes &&
plan.restartChannels.size === 0 &&
(plan.restartChannelAccounts?.size ?? 0) === 0
);
}
type ReloadRule = {
prefix: string;
kind: "restart" | "hot" | "none";
+3
View File
@@ -37,6 +37,7 @@ import { diffConfigPaths, diffGatewayReloadPaths } from "./config-diff.js";
import {
buildGatewayReloadPlan,
type ChannelKind,
isNoopGatewayReloadPlan,
resolveConfigReloadMetadata,
} from "./config-reload-plan.js";
import { resolveGatewayReloadSettings } from "./config-reload-settings.js";
@@ -377,6 +378,7 @@ describe("buildGatewayReloadPlan", () => {
expect(plan.restartReasons).toStrictEqual([]);
expect(plan.hotReasons).toStrictEqual([]);
expect(plan.noopPaths).toEqual([path]);
expect(isNoopGatewayReloadPlan(plan)).toBe(true);
},
);
@@ -481,6 +483,7 @@ describe("buildGatewayReloadPlan", () => {
expect(plan.restartChannels).toEqual(expectedChannels);
expect(plan.restartChannelAccounts).toEqual(expectedAccounts);
expect(isNoopGatewayReloadPlan(plan)).toBe(false);
});
it("restarts every channel whose config prefix matches", () => {
+2 -17
View File
@@ -33,6 +33,7 @@ import { createConfigAppliedRevisionTracker } from "./config-applied-revision.js
import { diffConfigPaths, diffGatewayReloadPaths } from "./config-diff.js";
import {
buildGatewayReloadPlan,
isNoopGatewayReloadPlan,
listPluginInstallTimestampMetadataPaths,
listPluginInstallWholeRecordPaths,
type GatewayReloadPlan,
@@ -86,22 +87,6 @@ function firstSkillsChangedPath(changedPaths: string[]): string | undefined {
return changedPaths.find(matchesSkillsInvalidationPrefix);
}
function isNoopReloadPlan(plan: GatewayReloadPlan): boolean {
return (
!plan.restartGateway &&
plan.hotReasons.length === 0 &&
!plan.reloadHooks &&
!plan.restartGmailWatcher &&
!plan.restartCron &&
!plan.restartHeartbeat &&
!plan.restartHealthMonitor &&
!plan.reloadPlugins &&
!plan.disposeMcpRuntimes &&
plan.restartChannels.size === 0 &&
(plan.restartChannelAccounts?.size ?? 0) === 0
);
}
type GatewayConfigReloader = {
stop: () => Promise<void>;
hotReloadStatus: () => GatewayHotReloadStatus;
@@ -710,7 +695,7 @@ export function startGatewayConfigReloader(opts: {
await commitReloadBaseline({ runtimeApplied: false });
return;
}
if (isNoopReloadPlan(plan) && !followUp.requiresRestart) {
if (isNoopGatewayReloadPlan(plan) && !followUp.requiresRestart) {
await opts.onConfigChange?.(plan, nextConfig);
// No-op plans still change the runtime config snapshot. Commit before
// marking applied so getRuntimeConfig() readers do not stay stale until restart.
@@ -17,7 +17,7 @@ import {
import { scheduleGatewaySigusr1Restart } from "../../infra/restart.js";
import { getActiveSecretsRuntimeSnapshot } from "../../secrets/runtime-state.js";
import { resolveEffectiveSharedGatewayAuth, resolveGatewayAuth } from "../auth.js";
import { buildGatewayReloadPlan } from "../config-reload-plan.js";
import { buildGatewayReloadPlan, isNoopGatewayReloadPlan } from "../config-reload-plan.js";
import { resolveGatewayReloadSettings } from "../config-reload-settings.js";
import { formatControlPlaneActor, type ControlPlaneActor } from "../control-plane-audit.js";
import { parseRestartRequestParams } from "./restart-request.js";
@@ -131,29 +131,13 @@ function queueSharedGatewayAuthGenerationRefresh(
});
}
function isNoopConfigReloadPlan(plan: ReturnType<typeof buildGatewayReloadPlan>): boolean {
return (
!plan.restartGateway &&
plan.hotReasons.length === 0 &&
!plan.reloadHooks &&
!plan.restartGmailWatcher &&
!plan.restartCron &&
!plan.restartHeartbeat &&
!plan.restartHealthMonitor &&
!plan.reloadPlugins &&
!plan.disposeMcpRuntimes &&
plan.restartChannels.size === 0 &&
(plan.restartChannelAccounts?.size ?? 0) === 0
);
}
function resolveConfigRestartRequirement(params: {
changedPaths: string[];
nextConfig: OpenClawConfig;
}): { requiresRestart: boolean; scheduleDirectRestart: boolean } {
const reloadSettings = resolveGatewayReloadSettings(params.nextConfig);
const plan = buildGatewayReloadPlan(params.changedPaths, { candidateConfig: params.nextConfig });
if (isNoopConfigReloadPlan(plan)) {
if (isNoopGatewayReloadPlan(plan)) {
return { requiresRestart: false, scheduleDirectRestart: false };
}
if (reloadSettings.mode === "off") {