solver-sdk
Version:
SDK для интеграции с Code Solver Backend API
129 lines • 6.21 kB
JavaScript
import { createWebSocketLogger } from './logger.js';
/**
* Класс для управления состоянием подключений
*/
export class ConnectionStateManager {
/**
* Создает новый менеджер состояния подключений
* @param {ConnectionStateManagerOptions} options Опции менеджера состояния подключений
*/
constructor(options = {}) {
/** Хранилище состояний подключений */
this.states = new Map();
this.reconnectStrategy = options.reconnectStrategy || 'exponential';
this.retryDelay = options.retryDelay || 1000;
this.maxRetryDelay = options.maxRetryDelay || 30000;
this.logger = options.logger || createWebSocketLogger('ConnectionStateManager');
}
/**
* Получает состояние подключения для указанного пространства имен
* @param {WebSocketNamespace} namespace Пространство имен
* @returns {ConnectionState} Состояние подключения
*/
getState(namespace) {
if (!this.states.has(namespace)) {
// Инициализируем состояние по умолчанию
this.states.set(namespace, {
lastConnectTime: 0,
reconnectAttempts: 0,
connected: false,
reconnecting: false
});
}
return this.states.get(namespace);
}
/**
* Устанавливает состояние подключения для указанного пространства имен
* @param {WebSocketNamespace} namespace Пространство имен
* @param {boolean} connected Состояние подключения
* @param {boolean} reconnecting Состояние переподключения
*/
setConnectionState(namespace, connected, reconnecting = false) {
const state = this.getState(namespace);
state.connected = connected;
state.reconnecting = reconnecting;
if (connected) {
state.lastConnectTime = Date.now();
// Сбрасываем счетчик попыток переподключения, если успешно подключились
if (!reconnecting) {
state.reconnectAttempts = 0;
}
}
this.states.set(namespace, state);
this.logger.debug(`Обновлено состояние подключения для ${namespace}`, {
connected,
reconnecting,
attempts: state.reconnectAttempts,
lastConnect: state.lastConnectTime
});
}
/**
* Увеличивает счетчик попыток переподключения для указанного пространства имен
* @param {WebSocketNamespace} namespace Пространство имен
* @returns {number} Новое количество попыток
*/
incrementReconnectAttempts(namespace) {
const state = this.getState(namespace);
state.reconnectAttempts++;
state.reconnecting = true;
this.states.set(namespace, state);
this.logger.debug(`Увеличен счетчик попыток переподключения для ${namespace}`, {
attempts: state.reconnectAttempts
});
return state.reconnectAttempts;
}
/**
* Рассчитывает задержку для переподключения на основе количества попыток и стратегии
* @param {WebSocketNamespace} namespace Пространство имен
* @returns {number} Задержка в миллисекундах
*/
calculateReconnectDelay(namespace) {
const state = this.getState(namespace);
const attempts = state.reconnectAttempts;
if (this.reconnectStrategy === 'exponential') {
// Экспоненциальный рост с фактором 1.5
const calculatedDelay = Math.min(this.retryDelay * Math.pow(1.5, attempts), this.maxRetryDelay);
// Добавляем случайный фактор (jitter) для предотвращения штормов переподключений
return calculatedDelay * (0.8 + Math.random() * 0.4);
}
else {
// Линейный рост
return Math.min(this.retryDelay * (attempts + 1), this.maxRetryDelay);
}
}
/**
* Сбрасывает счетчик попыток переподключения для указанного пространства имен
* @param {WebSocketNamespace} namespace Пространство имен
*/
resetReconnectAttempts(namespace) {
const state = this.getState(namespace);
state.reconnectAttempts = 0;
state.reconnecting = false;
this.states.set(namespace, state);
this.logger.debug(`Сброшен счетчик попыток переподключения для ${namespace}`);
}
/**
* Регистрирует успешное подключение
* @param {WebSocketNamespace} namespace Пространство имен
*/
registerSuccessfulConnection(namespace) {
this.setConnectionState(namespace, true, false);
this.resetReconnectAttempts(namespace);
}
/**
* Регистрирует отключение
* @param {WebSocketNamespace} namespace Пространство имен
*/
registerDisconnection(namespace) {
this.setConnectionState(namespace, false, false);
}
/**
* Регистрирует начало процесса переподключения
* @param {WebSocketNamespace} namespace Пространство имен
*/
registerReconnecting(namespace) {
this.setConnectionState(namespace, false, true);
this.incrementReconnectAttempts(namespace);
}
}
//# sourceMappingURL=connection-state-manager.js.map