fix: re-pin channel registry after deferred plugin reload

When preferSetupRuntimeForChannelPlugins is active, gateway boot performs
two plugin loads: a setup-runtime pass and a full reload after listen.
The initial pin captured the setup-entry snapshot. The deferred reload now
re-pins so getChannelPlugin() resolves against the full implementations.
This commit is contained in:
affsantos
2026-03-24 23:21:50 +01:00
committed by Peter Steinberger
parent 61d866838f
commit fae4492d92
2 changed files with 11 additions and 2 deletions

View File

@@ -236,7 +236,11 @@ export async function createGatewayRuntimeState(params: {
releasePluginRouteRegistry: () => {
// Releases both pinned HTTP-route and channel registries set at startup.
releasePinnedPluginHttpRouteRegistry(params.pluginRegistry);
releasePinnedPluginChannelRegistry(params.pluginRegistry);
// Release unconditionally (no registry arg): the channel pin may have
// been re-pinned to a deferred-reload registry that differs from the
// original params.pluginRegistry, so an identity-guarded release would
// be a no-op and leak the pin across in-process restarts.
releasePinnedPluginChannelRegistry();
},
httpServer,
httpServers,
@@ -258,7 +262,7 @@ export async function createGatewayRuntimeState(params: {
};
} catch (err) {
releasePinnedPluginHttpRouteRegistry(params.pluginRegistry);
releasePinnedPluginChannelRegistry(params.pluginRegistry);
releasePinnedPluginChannelRegistry();
throw err;
}
}

View File

@@ -53,6 +53,7 @@ import { createSubsystemLogger, runtimeForLogger } from "../logging/subsystem.js
import { resolveConfiguredDeferredChannelPluginIds } from "../plugins/channel-plugin-ids.js";
import { getGlobalHookRunner, runGlobalGatewayStopSafely } from "../plugins/hook-runner-global.js";
import { createEmptyPluginRegistry } from "../plugins/registry.js";
import { pinActivePluginChannelRegistry } from "../plugins/runtime.js";
import { createPluginRuntime } from "../plugins/runtime/index.js";
import type { PluginServicesHandle } from "../plugins/services.js";
import { getTotalQueueSize } from "../process/command-queue.js";
@@ -1195,6 +1196,10 @@ export async function startGatewayServer(
baseMethods,
logDiagnostics: false,
}));
// Re-pin: the deferred reload replaces setup-entry channel objects with
// full runtime implementations. Update the pinned channel registry so
// getChannelPlugin() resolves against the complete set.
pinActivePluginChannelRegistry(pluginRegistry);
}
({ browserControl, pluginServices } = await startGatewaySidecars({
cfg: cfgAtStart,