mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-03-22 07:36:33 +01:00
🔌 fix: Isolate Code-Server HTTP Agents to Prevent Socket Pool Contamination (#12311)
* 🔧 fix: Isolate HTTP agents for code-server axios requests Prevents socket hang up after 5s on Node 19+ when code executor has file attachments. follow-redirects (axios dep) leaks `socket.destroy` as a timeout listener on TCP sockets; with Node 19+ defaulting to keepAlive: true, tainted sockets re-enter the global pool and destroy active node-fetch requests in CodeExecutor after the idle timeout. Uses dedicated http/https agents with keepAlive: false for all axios calls targeting CODE_BASEURL in crud.js and process.js. Closes #12298 * ♻️ refactor: Extract code-server HTTP agents to shared module - Move duplicated agent construction from crud.js and process.js into a shared agents.js module to eliminate DRY violation - Switch process.js from raw `require('axios')` to `createAxiosInstance()` for proxy configuration parity with crud.js - Fix import ordering in process.js (agent constants no longer split imports) - Add 120s timeout to uploadCodeEnvFile (was the only code-server call without a timeout) * ✅ test: Add regression tests for code-server socket isolation - Add crud.spec.js covering getCodeOutputDownloadStream and uploadCodeEnvFile (agent options, timeout, URL, error handling) - Add socket pool isolation tests to process.spec.js asserting keepAlive:false agents are forwarded to axios - Update process.spec.js mocks for createAxiosInstance() migration * ♻️ refactor: Move code-server agents to packages/api Relocate agents.js from api/server/services/Files/Code/ to packages/api/src/utils/code.ts per workspace conventions. Consumers now import codeServerHttpAgent/codeServerHttpsAgent from @librechat/api.
This commit is contained in:
parent
7e74165c3c
commit
39f5f83a8a
7 changed files with 273 additions and 45 deletions
|
|
@ -10,11 +10,23 @@ jest.mock('@librechat/agents', () => ({
|
|||
|
||||
const mockSanitizeFilename = jest.fn();
|
||||
|
||||
jest.mock('@librechat/api', () => ({
|
||||
logAxiosError: jest.fn(),
|
||||
getBasePath: jest.fn(() => ''),
|
||||
sanitizeFilename: mockSanitizeFilename,
|
||||
}));
|
||||
const mockAxios = jest.fn().mockResolvedValue({
|
||||
data: Buffer.from('file-content'),
|
||||
});
|
||||
mockAxios.post = jest.fn();
|
||||
|
||||
jest.mock('@librechat/api', () => {
|
||||
const http = require('http');
|
||||
const https = require('https');
|
||||
return {
|
||||
logAxiosError: jest.fn(),
|
||||
getBasePath: jest.fn(() => ''),
|
||||
sanitizeFilename: mockSanitizeFilename,
|
||||
createAxiosInstance: jest.fn(() => mockAxios),
|
||||
codeServerHttpAgent: new http.Agent({ keepAlive: false }),
|
||||
codeServerHttpsAgent: new https.Agent({ keepAlive: false }),
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('librechat-data-provider', () => ({
|
||||
...jest.requireActual('librechat-data-provider'),
|
||||
|
|
@ -53,12 +65,6 @@ jest.mock('~/server/utils', () => ({
|
|||
determineFileType: jest.fn().mockResolvedValue({ mime: 'text/csv' }),
|
||||
}));
|
||||
|
||||
jest.mock('axios', () =>
|
||||
jest.fn().mockResolvedValue({
|
||||
data: Buffer.from('file-content'),
|
||||
}),
|
||||
);
|
||||
|
||||
const { createFile } = require('~/models');
|
||||
const { processCodeOutput } = require('../process');
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue