























@@ -26,6 +26,7 @@ const WINDOWS_STOPPED_FREE_EARLY_EXIT_GRACE_MS = 90_000;
2626export type GatewayRestartWaitOutcome =
2727| "healthy"
2828| "plugin-errors"
29+| "channel-errors"
2930| "version-mismatch"
3031| "stale-pids"
3132| "stopped-free"
@@ -38,6 +39,7 @@ export type GatewayRestartSnapshot = {
3839staleGatewayPids: number[];
3940gatewayVersion?: string | null;
4041activatedPluginErrors?: PluginHealthErrorSummary[];
42+channelProbeErrors?: Array<{ id: string; error: string }>;
4143expectedVersion?: string;
4244versionMismatch?: {
4345expected: string;
@@ -56,6 +58,7 @@ type GatewayReachability = {
5658reachable: boolean;
5759gatewayVersion: string | null;
5860activatedPluginErrors: PluginHealthErrorSummary[];
61+channelProbeErrors: Array<{ id: string; error: string }>;
5962};
60636164function hasListenerAttributionGap(portUsage: PortUsage): boolean {
@@ -154,13 +157,50 @@ function readActivatedPluginErrors(health: unknown): PluginHealthErrorSummary[]
154157});
155158}
156159160+function readChannelProbeErrors(health: unknown): Array<{ id: string; error: string }> {
161+if (!health || typeof health !== "object") {
162+return [];
163+}
164+const channels = (health as { channels?: unknown }).channels;
165+if (!channels || typeof channels !== "object" || Array.isArray(channels)) {
166+return [];
167+}
168+const errors: Array<{ id: string; error: string }> = [];
169+for (const [id, summary] of Object.entries(channels)) {
170+if (!summary || typeof summary !== "object") {
171+continue;
172+}
173+const probe = (summary as { probe?: unknown }).probe;
174+if (!probe || typeof probe !== "object") {
175+continue;
176+}
177+const ok = (probe as { ok?: unknown }).ok;
178+if (ok !== false) {
179+continue;
180+}
181+const error = (probe as { error?: unknown }).error;
182+errors.push({
183+ id,
184+error: typeof error === "string" && error.trim() ? error : "probe failed",
185+});
186+}
187+return errors;
188+}
189+157190function applyActivatedPluginErrors(snapshot: GatewayRestartSnapshot): GatewayRestartSnapshot {
158191if (!snapshot.activatedPluginErrors?.length) {
159192return snapshot;
160193}
161194return { ...snapshot, healthy: false };
162195}
163196197+function applyChannelProbeErrors(snapshot: GatewayRestartSnapshot): GatewayRestartSnapshot {
198+if (!snapshot.channelProbeErrors?.length) {
199+return snapshot;
200+}
201+return { ...snapshot, healthy: false };
202+}
203+164204async function confirmGatewayReachable(params: {
165205port: number;
166206includeHealthDetails?: boolean;
@@ -177,6 +217,7 @@ async function confirmGatewayReachable(params: {
177217reachable: probe.ok || looksLikeAuthClose(probe.close?.code, probe.close?.reason),
178218gatewayVersion: probe.server?.version ?? null,
179219activatedPluginErrors: readActivatedPluginErrors(probe.health),
220+channelProbeErrors: readChannelProbeErrors(probe.health),
180221};
181222}
182223@@ -217,13 +258,15 @@ export async function inspectGatewayRestart(params: {
217258const expectedVersion = normalizeOptionalString(params.expectedVersion);
218259let reachability: GatewayReachability | null = null;
219260let activatedPluginErrors: PluginHealthErrorSummary[] = [];
261+let channelProbeErrors: Array<{ id: string; error: string }> = [];
220262const loadReachability = async () => {
221263if (!reachability) {
222264reachability = await confirmGatewayReachable({
223265port: params.port,
224266includeHealthDetails: Boolean(expectedVersion),
225267});
226268activatedPluginErrors = reachability.activatedPluginErrors;
269+channelProbeErrors = reachability.channelProbeErrors;
227270}
228271return reachability;
229272};
@@ -251,19 +294,24 @@ export async function inspectGatewayRestart(params: {
251294try {
252295const reachable = await loadReachability();
253296if (reachable.reachable) {
254-return applyActivatedPluginErrors(
255-applyExpectedVersion(
256-{
257- runtime,
258- portUsage,
259-healthy: true,
260-staleGatewayPids: [],
261-gatewayVersion: reachable.gatewayVersion,
262- ...(reachable.activatedPluginErrors.length > 0
263- ? { activatedPluginErrors: reachable.activatedPluginErrors }
264- : {}),
265-},
266-expectedVersion,
297+return applyChannelProbeErrors(
298+applyActivatedPluginErrors(
299+applyExpectedVersion(
300+{
301+ runtime,
302+ portUsage,
303+healthy: true,
304+staleGatewayPids: [],
305+gatewayVersion: reachable.gatewayVersion,
306+ ...(reachable.activatedPluginErrors.length > 0
307+ ? { activatedPluginErrors: reachable.activatedPluginErrors }
308+ : {}),
309+ ...(reachable.channelProbeErrors.length > 0
310+ ? { channelProbeErrors: reachable.channelProbeErrors }
311+ : {}),
312+},
313+expectedVersion,
314+),
267315),
268316);
269317}
@@ -307,6 +355,9 @@ export async function inspectGatewayRestart(params: {
307355if (reachable.activatedPluginErrors.length > 0) {
308356healthy = false;
309357}
358+if (reachable.channelProbeErrors.length > 0) {
359+healthy = false;
360+}
310361} catch {
311362healthy = false;
312363}
@@ -340,17 +391,20 @@ export async function inspectGatewayRestart(params: {
340391]),
341392);
342393343-return applyActivatedPluginErrors(
344-applyExpectedVersion(
345-{
346- runtime,
347- portUsage,
348- healthy,
349- staleGatewayPids,
350- ...(gatewayVersion !== undefined ? { gatewayVersion } : {}),
351- ...(activatedPluginErrors.length ? { activatedPluginErrors } : {}),
352-},
353-expectedVersion,
394+return applyChannelProbeErrors(
395+applyActivatedPluginErrors(
396+applyExpectedVersion(
397+{
398+ runtime,
399+ portUsage,
400+ healthy,
401+ staleGatewayPids,
402+ ...(gatewayVersion !== undefined ? { gatewayVersion } : {}),
403+ ...(activatedPluginErrors.length ? { activatedPluginErrors } : {}),
404+ ...(channelProbeErrors.length ? { channelProbeErrors } : {}),
405+},
406+expectedVersion,
407+),
354408),
355409);
356410}
@@ -415,6 +469,9 @@ export async function waitForGatewayHealthyRestart(params: {
415469if (snapshot.activatedPluginErrors?.length) {
416470return withWaitContext(snapshot, "plugin-errors", attempt * delayMs);
417471}
472+if (snapshot.channelProbeErrors?.length) {
473+return withWaitContext(snapshot, "channel-errors", attempt * delayMs);
474+}
418475if (snapshot.versionMismatch) {
419476return withWaitContext(snapshot, "version-mismatch", attempt * delayMs);
420477}
@@ -493,6 +550,12 @@ export function renderRestartDiagnostics(snapshot: GatewayRestartSnapshot): stri
493550lines.push(`- ${plugin.id}: ${plugin.error}`);
494551}
495552}
553+if (snapshot.channelProbeErrors?.length) {
554+lines.push("Channel health probe errors:");
555+for (const channel of snapshot.channelProbeErrors) {
556+lines.push(`- ${channel.id}: ${channel.error}`);
557+}
558+}
496559const runtimeSummary = [
497560snapshot.runtime.status ? `status=${snapshot.runtime.status}` : null,
498561snapshot.runtime.state ? `state=${snapshot.runtime.state}` : null,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。