Add queued sending for Codex App drafts

Also include WebSocket heartbeat handling to keep idle connections healthy.
This commit is contained in:
shiyue
2026-06-22 22:18:27 +08:00
parent e15736e302
commit 844281ab4c
4 changed files with 766 additions and 29 deletions

View File

@@ -4942,6 +4942,7 @@ const server = http.createServer((req, res) => {
// === WebSocket Server ===
const wss = new WebSocketServer({ noServer: true });
const WS_HEARTBEAT_INTERVAL_MS = 30000;
server.on('upgrade', (req, socket, head) => {
let pathname = '';
@@ -4978,8 +4979,14 @@ wss.on('connection', (ws, req) => {
let authToken = null;
const wsId = crypto.randomBytes(4).toString('hex'); // short id for log correlation
const wsConnectTime = new Date().toISOString();
ws.isAlive = true;
ws._ccWebId = wsId;
plog('INFO', 'ws_connect', { wsId });
ws.on('pong', () => {
ws.isAlive = true;
});
ws.on('message', (raw) => {
let msg;
try {
@@ -5120,6 +5127,26 @@ wss.on('connection', (ws, req) => {
});
});
// WebSocket 心跳:避免反向代理因空闲连接关闭 /ws。
const wsHeartbeatTimer = setInterval(() => {
for (const client of wss.clients) {
if (client.isAlive === false) {
client.terminate();
continue;
}
client.isAlive = false;
if (client.readyState === 1) {
try {
client.ping();
} catch (err) {
plog('WARN', 'ws_ping_failed', { wsId: client._ccWebId || null, error: err.message });
client.terminate();
}
}
}
}, WS_HEARTBEAT_INTERVAL_MS);
if (typeof wsHeartbeatTimer.unref === 'function') wsHeartbeatTimer.unref();
// === Notify Config Handlers ===
function handleSaveNotifyConfig(ws, newConfig) {
if (!newConfig || !newConfig.provider) {