LibreChat/api/server/services/initializeOAuthReconnectManager.js
Marco Beretta 784582850a
🧯 fix: Guard SSE Writes and Interval Cleanups Against Crashes (#17462)
* fix: Harden Timer Sweeps, SSE Writes, and Violation Counters

Guard SSE writes against ended or destroyed responses through one helper, catch and single-flight the job store and TTL cache cleanup timers, serialize in-process counter updates, cap the violation log, prune stale OAuth failure records, batch the active-job lookup, and count Redis keys with DBSIZE.

* refactor: Drop the redundant violation log entry copy

* refactor: Log single-flight sweep failures from the API package

* test: Cover active generation listing and client disconnect mid-stream

* refactor: Configure violation log retention and move title timeout into the API package

* feat: Configure OAuth failure retention through mcpSettings

* fix: Prune OAuth failures promptly under short retention
2026-10-27 23:06:58 +01:00

53 lines
2.1 KiB
JavaScript

const { logger, getTenantId } = require('@librechat/data-schemas');
const {
prepareMCPAuthorizationMutation,
createOAuthReconnectionTracker,
} = require('@librechat/api');
const { CacheKeys } = require('librechat-data-provider');
const { createOAuthReconnectionManager, getFlowStateManager, getMCPManager } = require('~/config');
const { findToken, updateToken, createToken, deleteTokens } = require('~/models');
const { getLogStores } = require('~/cache');
const { getAppConfig, invalidateCachedTools } = require('~/server/services/Config');
const {
clearMCPAuthorizationFenceRetry,
persistMCPAuthorizationFenceRetry,
} = require('~/server/services/MCPAuthorizationFenceRetry');
/**
* Initialize OAuth reconnect manager
*/
async function initializeOAuthReconnectManager() {
try {
const flowManager = getFlowStateManager(getLogStores(CacheKeys.FLOWS));
const tokenMethods = {
findToken,
updateToken,
createToken,
deleteTokens,
};
const startupConfig = await getAppConfig({ baseOnly: true });
await createOAuthReconnectionManager(
flowManager,
tokenMethods,
createOAuthReconnectionTracker(startupConfig),
undefined,
async (scope) => {
const appConfig = await getAppConfig({ tenantId: getTenantId(), userId: scope.userId });
return prepareMCPAuthorizationMutation(scope, {
invalidateRecoveryGeneration: invalidateCachedTools,
persistPublicationRetry: persistMCPAuthorizationFenceRetry,
clearPublicationRetry: clearMCPAuthorizationFenceRetry,
clearLocalRecovery: (userId, serverName) =>
getMCPManager()?.clearCatalogRecoveryState?.(userId, serverName),
retryDelaysMs: appConfig?.mcpSettings?.catalogRecovery?.authorizationFenceRetryMs,
attemptTimeoutMs: appConfig?.mcpSettings?.catalogRecovery?.authorizationFenceTimeoutMs,
});
},
);
logger.info(`OAuth reconnect manager initialized successfully.`);
} catch (error) {
logger.error('Failed to initialize OAuth reconnect manager:', error);
}
}
module.exports = initializeOAuthReconnectManager;