Files
esengine/packages/network/src/Config/NetworkConfigManager.ts

478 lines
15 KiB
TypeScript
Raw Normal View History

2025-08-09 18:56:19 +08:00
/**
*
*/
import {
NETWORK_CONFIG,
SYNCVAR_CONFIG,
MESSAGE_CONFIG,
SERIALIZATION_CONFIG,
TSRPC_CONFIG,
AUTHORITY_CONFIG,
PERFORMANCE_CONFIG
} from '../constants/NetworkConstants';
/**
*
*/
export interface INetworkConfig {
[key: string]: unknown;
/** 连接配置 */
connection: {
timeout: number;
maxReconnectAttempts: number;
reconnectDelay: number;
};
/** 心跳配置 */
heartbeat: {
interval: number;
timeout: number;
maxConsecutiveLoss: number;
packetSize: number;
enableAdaptiveInterval: boolean;
rttHistorySize: number;
};
/** SyncVar配置 */
syncVar: {
cacheTimeout: number;
defaultThrottleMs: number;
maxFieldNumber: number;
minFieldNumber: number;
};
/** 消息配置 */
message: {
maxSequenceNumber: number;
maxHeaderSize: number;
maxPayloadSize: number;
defaultTimeout: number;
maxBatchSize: number;
};
/** 序列化配置 */
serialization: {
defaultCompressionLevel: number;
minCompressionSize: number;
initialBufferSize: number;
maxBufferSize: number;
};
/** TSRPC配置 */
tsrpc: {
defaultServerUrl: string;
defaultTimeout: number;
heartbeatInterval: number;
heartbeatTimeout: number;
poolConfig: {
minConnections: number;
maxConnections: number;
idleTimeout: number;
};
};
/** 权限配置 */
authority: {
minPriority: number;
maxPriority: number;
defaultRulePriority: number;
};
/** 性能监控配置 */
performance: {
statsCollectionInterval: number;
statsRetentionTime: number;
warningThresholds: {
rtt: number;
packetLoss: number;
jitter: number;
cpuUsage: number;
memoryUsage: number;
};
};
}
/**
*
*/
export interface IConfigUpdateEvent<T = unknown> {
path: string;
oldValue: T;
newValue: T;
timestamp: number;
}
/**
*
*
*
*/
export class NetworkConfigManager {
private static _instance: NetworkConfigManager | null = null;
private _config: INetworkConfig;
private _updateListeners: Map<string, Array<(event: IConfigUpdateEvent) => void>> = new Map();
private constructor() {
this._config = this.createDefaultConfig();
}
public static get Instance(): NetworkConfigManager {
if (!NetworkConfigManager._instance) {
NetworkConfigManager._instance = new NetworkConfigManager();
}
return NetworkConfigManager._instance;
}
/**
*
*/
private createDefaultConfig(): INetworkConfig {
return {
connection: {
timeout: NETWORK_CONFIG.DEFAULT_CONNECTION_TIMEOUT,
maxReconnectAttempts: NETWORK_CONFIG.DEFAULT_MAX_RECONNECT_ATTEMPTS,
reconnectDelay: NETWORK_CONFIG.DEFAULT_RECONNECT_DELAY
},
heartbeat: {
interval: NETWORK_CONFIG.DEFAULT_HEARTBEAT_INTERVAL,
timeout: NETWORK_CONFIG.DEFAULT_HEARTBEAT_TIMEOUT,
maxConsecutiveLoss: NETWORK_CONFIG.DEFAULT_MAX_CONSECUTIVE_LOSS,
packetSize: NETWORK_CONFIG.DEFAULT_HEARTBEAT_PACKET_SIZE,
enableAdaptiveInterval: true,
rttHistorySize: NETWORK_CONFIG.DEFAULT_RTT_HISTORY_SIZE
},
syncVar: {
cacheTimeout: SYNCVAR_CONFIG.DEFAULT_CACHE_TIMEOUT,
defaultThrottleMs: SYNCVAR_CONFIG.DEFAULT_THROTTLE_MS,
maxFieldNumber: SYNCVAR_CONFIG.MAX_FIELD_NUMBER,
minFieldNumber: SYNCVAR_CONFIG.MIN_FIELD_NUMBER
},
message: {
maxSequenceNumber: MESSAGE_CONFIG.MAX_SEQUENCE_NUMBER,
maxHeaderSize: MESSAGE_CONFIG.MAX_HEADER_SIZE,
maxPayloadSize: MESSAGE_CONFIG.MAX_PAYLOAD_SIZE,
defaultTimeout: MESSAGE_CONFIG.DEFAULT_MESSAGE_TIMEOUT,
maxBatchSize: MESSAGE_CONFIG.MAX_BATCH_SIZE
},
serialization: {
defaultCompressionLevel: SERIALIZATION_CONFIG.DEFAULT_COMPRESSION_LEVEL,
minCompressionSize: SERIALIZATION_CONFIG.MIN_COMPRESSION_SIZE,
initialBufferSize: SERIALIZATION_CONFIG.INITIAL_BUFFER_SIZE,
maxBufferSize: SERIALIZATION_CONFIG.MAX_BUFFER_SIZE
},
tsrpc: {
defaultServerUrl: TSRPC_CONFIG.DEFAULT_SERVER_URL,
defaultTimeout: TSRPC_CONFIG.DEFAULT_TIMEOUT,
heartbeatInterval: TSRPC_CONFIG.DEFAULT_HEARTBEAT.interval,
heartbeatTimeout: TSRPC_CONFIG.DEFAULT_HEARTBEAT.timeout,
poolConfig: {
minConnections: TSRPC_CONFIG.DEFAULT_POOL_CONFIG.minConnections,
maxConnections: TSRPC_CONFIG.DEFAULT_POOL_CONFIG.maxConnections,
idleTimeout: TSRPC_CONFIG.DEFAULT_POOL_CONFIG.idleTimeout
}
},
authority: {
minPriority: AUTHORITY_CONFIG.MIN_PRIORITY,
maxPriority: AUTHORITY_CONFIG.MAX_PRIORITY,
defaultRulePriority: AUTHORITY_CONFIG.DEFAULT_RULE_PRIORITY
},
performance: {
statsCollectionInterval: PERFORMANCE_CONFIG.STATS_COLLECTION_INTERVAL,
statsRetentionTime: PERFORMANCE_CONFIG.STATS_RETENTION_TIME,
warningThresholds: {
rtt: PERFORMANCE_CONFIG.WARNING_THRESHOLDS.RTT,
packetLoss: PERFORMANCE_CONFIG.WARNING_THRESHOLDS.PACKET_LOSS,
jitter: PERFORMANCE_CONFIG.WARNING_THRESHOLDS.JITTER,
cpuUsage: PERFORMANCE_CONFIG.WARNING_THRESHOLDS.CPU_USAGE,
memoryUsage: PERFORMANCE_CONFIG.WARNING_THRESHOLDS.MEMORY_USAGE
}
}
};
}
/**
*
*/
public getConfig(): Readonly<INetworkConfig> {
return this._config;
}
/**
*
*
* @param path - 使
* @returns
*/
public get<T = unknown>(path: string): T {
const keys = path.split('.');
let current: unknown = this._config;
for (const key of keys) {
if (typeof current !== 'object' || current === null || !(key in current)) {
throw new Error(`配置路径不存在: ${path}`);
}
current = (current as Record<string, unknown>)[key];
}
return current as T;
}
/**
*
*
* @param path -
* @param value -
*/
public set<T = unknown>(path: string, value: T): void {
const keys = path.split('.');
const lastKey = keys.pop()!;
let current = this._config as Record<string, unknown>;
// 导航到父对象
for (const key of keys) {
if (typeof current[key] !== 'object' || current[key] === null) {
throw new Error(`配置路径无效: ${path}`);
}
current = current[key] as Record<string, unknown>;
}
const oldValue = current[lastKey];
// 验证新值
this.validateConfigValue(path, value);
// 设置新值
current[lastKey] = value;
// 触发更新事件
this.emitConfigUpdate({
path,
oldValue,
newValue: value,
timestamp: Date.now()
});
}
/**
*
*
* @param updates -
*/
public update(updates: Partial<INetworkConfig>): void {
const flatUpdates = this.flattenObject(updates as unknown as Record<string, unknown>);
for (const [path, value] of Object.entries(flatUpdates)) {
this.set(path, value);
}
}
/**
*
*/
public reset(): void {
const oldConfig = { ...this._config };
this._config = this.createDefaultConfig();
this.emitConfigUpdate({
path: '',
oldValue: oldConfig,
newValue: this._config,
timestamp: Date.now()
});
}
/**
*
*
* @param path -
* @param listener -
*/
public addUpdateListener(path: string, listener: (event: IConfigUpdateEvent) => void): void {
if (!this._updateListeners.has(path)) {
this._updateListeners.set(path, []);
}
this._updateListeners.get(path)!.push(listener);
}
/**
*
*
* @param path -
* @param listener -
*/
public removeUpdateListener(path: string, listener: (event: IConfigUpdateEvent) => void): void {
const listeners = this._updateListeners.get(path);
if (listeners) {
const index = listeners.indexOf(listener);
if (index !== -1) {
listeners.splice(index, 1);
}
}
}
/**
*
*/
public loadFromEnv(): void {
const envConfig = this.parseEnvConfig();
if (Object.keys(envConfig).length > 0) {
this.update(envConfig);
}
}
/**
* JSON对象加载配置
*
* @param config -
*/
public loadFromObject(config: Partial<INetworkConfig>): void {
this.validateConfig(config);
this.update(config);
}
/**
* JSON
*/
public exportConfig(): INetworkConfig {
return JSON.parse(JSON.stringify(this._config));
}
/**
*
*/
private validateConfigValue(path: string, value: unknown): void {
// 基本类型检查
if (path.includes('timeout') || path.includes('interval') || path.includes('delay')) {
if (typeof value !== 'number' || value < 0) {
throw new Error(`配置值必须是非负数: ${path}`);
}
}
if (path.includes('size') && typeof value === 'number' && value <= 0) {
throw new Error(`大小配置必须是正数: ${path}`);
}
if (path.includes('url') && typeof value !== 'string') {
throw new Error(`URL配置必须是字符串: ${path}`);
}
// 特定路径验证
if (path === 'syncVar.maxFieldNumber' && typeof value === 'number' && value > SYNCVAR_CONFIG.MAX_FIELD_NUMBER) {
throw new Error(`字段编号不能超过 ${SYNCVAR_CONFIG.MAX_FIELD_NUMBER}`);
}
if (path === 'syncVar.minFieldNumber' && typeof value === 'number' && value < SYNCVAR_CONFIG.MIN_FIELD_NUMBER) {
throw new Error(`字段编号不能小于 ${SYNCVAR_CONFIG.MIN_FIELD_NUMBER}`);
}
}
/**
*
*/
private validateConfig(config: Partial<INetworkConfig>): void {
// 递归验证配置结构
const flatConfig = this.flattenObject(config);
for (const [path, value] of Object.entries(flatConfig)) {
this.validateConfigValue(path, value);
}
}
/**
*
*/
private flattenObject(obj: Record<string, unknown>, prefix = ''): Record<string, unknown> {
const flattened: Record<string, unknown> = {};
for (const [key, value] of Object.entries(obj)) {
const newKey = prefix ? `${prefix}.${key}` : key;
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
Object.assign(flattened, this.flattenObject(value as Record<string, unknown>, newKey));
} else {
flattened[newKey] = value;
}
}
return flattened;
}
/**
*
*/
private parseEnvConfig(): Partial<INetworkConfig> {
const config: Partial<INetworkConfig> = {};
// 连接配置
if (process.env.NETWORK_CONNECTION_TIMEOUT) {
config.connection = {
timeout: parseInt(process.env.NETWORK_CONNECTION_TIMEOUT, 10),
maxReconnectAttempts: NETWORK_CONFIG.DEFAULT_MAX_RECONNECT_ATTEMPTS,
reconnectDelay: NETWORK_CONFIG.DEFAULT_RECONNECT_DELAY
};
}
// 心跳配置
if (process.env.NETWORK_HEARTBEAT_INTERVAL) {
config.heartbeat = {
interval: parseInt(process.env.NETWORK_HEARTBEAT_INTERVAL, 10),
timeout: NETWORK_CONFIG.DEFAULT_HEARTBEAT_TIMEOUT,
maxConsecutiveLoss: NETWORK_CONFIG.DEFAULT_MAX_CONSECUTIVE_LOSS,
packetSize: NETWORK_CONFIG.DEFAULT_HEARTBEAT_PACKET_SIZE,
enableAdaptiveInterval: true,
rttHistorySize: NETWORK_CONFIG.DEFAULT_RTT_HISTORY_SIZE
};
}
// TSRPC配置
if (process.env.TSRPC_SERVER_URL) {
config.tsrpc = {
defaultServerUrl: process.env.TSRPC_SERVER_URL,
defaultTimeout: TSRPC_CONFIG.DEFAULT_TIMEOUT,
heartbeatInterval: TSRPC_CONFIG.DEFAULT_HEARTBEAT.interval,
heartbeatTimeout: TSRPC_CONFIG.DEFAULT_HEARTBEAT.timeout,
poolConfig: {
minConnections: TSRPC_CONFIG.DEFAULT_POOL_CONFIG.minConnections,
maxConnections: TSRPC_CONFIG.DEFAULT_POOL_CONFIG.maxConnections,
idleTimeout: TSRPC_CONFIG.DEFAULT_POOL_CONFIG.idleTimeout
}
};
}
return config;
}
/**
*
*/
private emitConfigUpdate(event: IConfigUpdateEvent): void {
// 触发具体路径的监听器
const listeners = this._updateListeners.get(event.path);
if (listeners) {
listeners.forEach(listener => {
try {
listener(event);
} catch (error) {
console.error(`配置更新监听器错误 (${event.path}):`, error);
}
});
}
// 触发全局监听器
const globalListeners = this._updateListeners.get('');
if (globalListeners) {
globalListeners.forEach(listener => {
try {
listener(event);
} catch (error) {
console.error('全局配置更新监听器错误:', error);
}
});
}
}
}
/**
*
*/
export const NetworkConfig = NetworkConfigManager.Instance;