fix(gateway): stop stale-socket restarts before first event (#38643)

* fix(gateway): guard stale-socket restarts by event liveness

* fix(gateway): centralize connect-time liveness tracking

* fix(web): apply connected status patch atomically

* fix(gateway): require active socket for stale checks

* fix(gateway): ignore inherited stale event timestamps
This commit is contained in:
Tak Hoffman
2026-03-07 00:58:08 -06:00
committed by GitHub
parent a5c07fa115
commit 8873e13f1e
11 changed files with 157 additions and 26 deletions

View File

@@ -1,6 +1,7 @@
import type { Client } from "@buape/carbon";
import type { GatewayPlugin } from "@buape/carbon/gateway";
import { createArmableStallWatchdog } from "../../channels/transport/stall-watchdog.js";
import { createConnectedChannelStatusPatch } from "../../gateway/channel-status-patches.js";
import { danger } from "../../globals.js";
import type { RuntimeEnv } from "../../runtime.js";
import { attachDiscordGatewayLogging } from "../gateway-logging.js";
@@ -180,8 +181,7 @@ export async function runDiscordGatewayLifecycle(params: {
let sawConnected = gateway?.isConnected === true;
if (sawConnected) {
pushStatus({
connected: true,
lastConnectedAt: at,
...createConnectedChannelStatusPatch(at),
lastDisconnect: null,
});
}
@@ -194,9 +194,7 @@ export async function runDiscordGatewayLifecycle(params: {
const connectedAt = Date.now();
reconnectStallWatchdog.disarm();
pushStatus({
connected: true,
lastEventAt: connectedAt,
lastConnectedAt: connectedAt,
...createConnectedChannelStatusPatch(connectedAt),
lastDisconnect: null,
});
if (helloConnectedPollId) {
@@ -253,9 +251,7 @@ export async function runDiscordGatewayLifecycle(params: {
if (gateway?.isConnected && !lifecycleStopping) {
const at = Date.now();
pushStatus({
connected: true,
lastEventAt: at,
lastConnectedAt: at,
...createConnectedChannelStatusPatch(at),
lastDisconnect: null,
});
}

View File

@@ -36,6 +36,7 @@ import {
resolveDefaultGroupPolicy,
warnMissingProviderGroupPolicyFallbackOnce,
} from "../../config/runtime-group-policy.js";
import { createConnectedChannelStatusPatch } from "../../gateway/channel-status-patches.js";
import { danger, logVerbose, shouldLogVerbose, warn } from "../../globals.js";
import { formatErrorMessage } from "../../infra/errors.js";
import { createDiscordRetryRunner } from "../../infra/retry-policy.js";
@@ -752,7 +753,7 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) {
botUserId && botUserName ? `${botUserId} (${botUserName})` : (botUserId ?? botUserName ?? "");
runtime.log?.(`logged in to discord${botIdentity ? ` as ${botIdentity}` : ""}`);
if (lifecycleGateway?.isConnected) {
opts.setStatus?.({ connected: true });
opts.setStatus?.(createConnectedChannelStatusPatch());
}
lifecycleStarted = true;