mirror of
https://github.com/cnlimiter/codex-register.git
synced 2026-05-06 20:02:51 +08:00
fix: route batch websocket fallback by task type
This commit is contained in:
@@ -1306,7 +1306,7 @@ function connectBatchWebSocket(batchId) {
|
||||
|
||||
if (shouldPoll && currentBatch) {
|
||||
console.log('切换到轮询模式');
|
||||
startOutlookBatchPolling(currentBatch.batch_id);
|
||||
startCurrentBatchPolling(currentBatch.batch_id);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1314,12 +1314,12 @@ function connectBatchWebSocket(batchId) {
|
||||
console.error('批量任务 WebSocket 错误:', error);
|
||||
stopBatchWebSocketHeartbeat();
|
||||
// 切换到轮询
|
||||
startOutlookBatchPolling(batchId);
|
||||
startCurrentBatchPolling(batchId);
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.error('批量任务 WebSocket 连接失败:', error);
|
||||
startOutlookBatchPolling(batchId);
|
||||
startCurrentBatchPolling(batchId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1332,6 +1332,15 @@ function disconnectBatchWebSocket() {
|
||||
}
|
||||
}
|
||||
|
||||
function startCurrentBatchPolling(batchId) {
|
||||
if (isOutlookBatchMode) {
|
||||
startOutlookBatchPolling(batchId);
|
||||
return;
|
||||
}
|
||||
|
||||
startBatchPolling(batchId);
|
||||
}
|
||||
|
||||
// 开始批量任务心跳
|
||||
function startBatchWebSocketHeartbeat() {
|
||||
stopBatchWebSocketHeartbeat();
|
||||
|
||||
133
tests/test_batch_websocket_fallback.cjs
Normal file
133
tests/test_batch_websocket_fallback.cjs
Normal file
@@ -0,0 +1,133 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const vm = require('node:vm');
|
||||
|
||||
const APP_JS_PATH = '/Users/zhoukailian/.config/superpowers/worktrees/codex-manager/repro-batch-monitor/static/js/app.js';
|
||||
|
||||
function createElementStub() {
|
||||
return {
|
||||
style: {},
|
||||
dataset: {},
|
||||
value: '',
|
||||
checked: false,
|
||||
disabled: false,
|
||||
innerHTML: '',
|
||||
textContent: '',
|
||||
className: '',
|
||||
appendChild() {},
|
||||
addEventListener() {},
|
||||
removeEventListener() {},
|
||||
querySelector() {
|
||||
return createElementStub();
|
||||
},
|
||||
querySelectorAll() {
|
||||
return [];
|
||||
},
|
||||
closest() {
|
||||
return null;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function createSandbox() {
|
||||
const sandbox = {
|
||||
console,
|
||||
setTimeout,
|
||||
clearTimeout,
|
||||
setInterval: () => 1,
|
||||
clearInterval: () => {},
|
||||
Event: class Event {
|
||||
constructor(type) {
|
||||
this.type = type;
|
||||
}
|
||||
},
|
||||
document: {
|
||||
getElementById() {
|
||||
return createElementStub();
|
||||
},
|
||||
createElement() {
|
||||
return createElementStub();
|
||||
},
|
||||
addEventListener() {},
|
||||
querySelector() {
|
||||
return createElementStub();
|
||||
},
|
||||
querySelectorAll() {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
sessionStorage: {
|
||||
getItem() {
|
||||
return null;
|
||||
},
|
||||
setItem() {},
|
||||
removeItem() {},
|
||||
},
|
||||
toast: {
|
||||
info() {},
|
||||
success() {},
|
||||
warning() {},
|
||||
error() {},
|
||||
},
|
||||
api: {
|
||||
get() {
|
||||
throw new Error('api.get should not be called in this test');
|
||||
},
|
||||
post() {
|
||||
throw new Error('api.post should not be called in this test');
|
||||
},
|
||||
},
|
||||
window: null,
|
||||
WebSocket: null,
|
||||
};
|
||||
|
||||
sandbox.window = sandbox;
|
||||
sandbox.window.location = { protocol: 'http:', host: '127.0.0.1:8003' };
|
||||
|
||||
vm.createContext(sandbox);
|
||||
vm.runInContext(fs.readFileSync(APP_JS_PATH, 'utf8'), sandbox, { filename: 'app.js' });
|
||||
|
||||
return sandbox;
|
||||
}
|
||||
|
||||
async function runFallback(mode) {
|
||||
const sandbox = createSandbox();
|
||||
|
||||
vm.runInContext(
|
||||
`
|
||||
var __calls = [];
|
||||
currentBatch = { batch_id: 'test-batch' };
|
||||
isOutlookBatchMode = ${mode === 'outlook' ? 'true' : 'false'};
|
||||
batchCompleted = false;
|
||||
batchFinalStatus = null;
|
||||
startOutlookBatchPolling = function(batchId) { __calls.push(['outlook', batchId]); };
|
||||
startBatchPolling = function(batchId) { __calls.push(['batch', batchId]); };
|
||||
WebSocket = function(url) {
|
||||
this.url = url;
|
||||
this.readyState = 0;
|
||||
setTimeout(() => {
|
||||
if (this.onerror) {
|
||||
this.onerror({ type: 'error' });
|
||||
}
|
||||
}, 0);
|
||||
};
|
||||
WebSocket.OPEN = 1;
|
||||
connectBatchWebSocket('test-batch');
|
||||
`,
|
||||
sandbox,
|
||||
);
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 20));
|
||||
return JSON.parse(vm.runInContext('JSON.stringify(__calls)', sandbox));
|
||||
}
|
||||
|
||||
test('normal batch websocket fallback uses standard batch polling', async () => {
|
||||
const calls = await runFallback('batch');
|
||||
assert.deepEqual(calls, [['batch', 'test-batch']]);
|
||||
});
|
||||
|
||||
test('outlook batch websocket fallback uses outlook polling', async () => {
|
||||
const calls = await runFallback('outlook');
|
||||
assert.deepEqual(calls, [['outlook', 'test-batch']]);
|
||||
});
|
||||
Reference in New Issue
Block a user