{"version":3,"sources":["../src/utils/nacos.ts"],"sourcesContent":["import axios from 'axios';\nimport type { ServiceInstanceInfo } from '../types';\nimport { getConfig, getGlobalState, updateConfigPort } from './config';\nimport { logger } from './logger';\n\n/**\n * Nacos 实例接口\n * 定义了从 Nacos 服务器返回的实例数据结构\n */\nexport interface NacosInstance {\n  instanceId: string;           // 实例 ID\n  ip: string;                   // 实例 IP 地址\n  port: number;                 // 实例端口\n  weight: number;               // 实例权重\n  healthy: boolean;             // 实例是否健康\n  enabled: boolean;             // 实例是否启用\n  ephemeral: boolean;           // 是否为临时实例\n  clusterName: string;          // 集群名称\n  serviceName: string;          // 服务名称\n  metadata: Record<string, string>; // 实例元数据\n  instanceHeartBeatInterval?: number; // 心跳间隔\n}\n\n/**\n * Nacos 服务列表响应接口\n * 定义了 Nacos 服务实例列表查询的响应结构\n */\nexport interface NacosServiceListResponse {\n  name?: string;                // 服务名称\n  groupName?: string;           // 分组名称\n  clusters?: string;            // 集群名称\n  cacheMillis?: number;         // 缓存时间\n  hosts: NacosInstance[];       // 实例列表\n  lastRefTime?: number;         // 最后刷新时间\n  checksum?: string;            // 校验和\n  allIPs?: boolean;             // 是否包含所有 IP\n  env?: string;                 // 环境\n}\n\n/**\n * 注册服务实例到 Nacos\n * 将当前服务实例注册到 Nacos 服务注册中心\n *\n * @param port 服务端口\n * @returns 注册是否成功\n */\nexport async function registerServiceInstance(port: number): Promise<boolean> {\n  const config = getConfig();\n\n  // 检查泳道功能是否启用\n  if (!config.isLaneEnabled) {\n    logger.debug('🚫 泳道功能未启用，跳过服务注册');\n    return true;\n  }\n\n  try {\n    logger.debug(`🚀 开始服务注册流程，时间戳: ${new Date().toISOString()}`);\n\n    // 更新配置中的端口\n    updateConfigPort(port);\n\n    // 构建注册请求\n    const registrationUrl = `${config.nacosUrl}/nacos/v1/ns/instance`;\n    const params = new URLSearchParams();\n\n    // 设置基本参数\n    params.append('serviceName', config.serviceName);\n    params.append('ip', config.host);\n    params.append('port', port.toString());\n    params.append('weight', '1.0');\n    params.append('healthy', 'true');\n    params.append('metadata', JSON.stringify(config.metadata));\n    params.append('clusterName', config.currentLaneId || 'DEFAULT');\n    params.append('ephemeral', 'true');\n\n    // 添加过期时间参数\n    params.append('ipDeleteTimeout', config.instanceTtl.toString());\n    params.append('instanceHeartBeatInterval', config.heartbeatInterval.toString());\n    params.append('instanceHeartBeatTimeOut', (config.heartbeatInterval * 2).toString());\n\n    // 发送注册请求\n    logger.debug(`📤 发送注册请求到 Nacos: ${registrationUrl}`);\n\n    const response = await axios.post(registrationUrl, params, {\n      headers: {\n        'Content-Type': 'application/x-www-form-urlencoded',\n        'User-Agent': 'Nuxt3-LaneManager/1.0',\n      },\n      timeout: config.registrationTimeout,\n    });\n\n    // 记录响应结果\n    logger.debug(`📥 注册响应状态码: ${response.status}, 数据: ${JSON.stringify(response.data)}`);\n\n    if (response.status === 200 && response.data === 'ok') {\n      logger.success(`✅ 服务注册成功: ${config.serviceName}@${config.host}:${port} (泳道: ${config.currentLaneId})`);\n\n      // 设置全局状态\n      const globalState = getGlobalState();\n      globalState._laneMgrRegistered = true;\n      globalState._laneMgrPort = port;\n\n      // 启动心跳\n      startHeartbeat(port);\n\n      return true;\n    } else {\n      logger.error(`❌ 服务注册失败: ${response.data}`);\n      return false;\n    }\n  } catch (error) {\n    logger.error(`❌ 服务注册错误: ${error instanceof Error ? error.message : String(error)}`);\n    if (axios.isAxiosError(error) && error.response) {\n      logger.error(`🔴 HTTP状态码: ${error.response.status}, 响应: ${JSON.stringify(error.response.data)}`);\n    }\n    return false;\n  }\n}\n\n/**\n * 从 Nacos 注销服务实例\n * 从 Nacos 服务注册中心注销当前服务实例\n *\n * @param port 服务端口\n * @returns 注销是否成功\n */\nexport async function deregisterServiceInstance(port: number): Promise<boolean> {\n  const config = getConfig();\n\n  // 检查泳道功能是否启用\n  if (!config.isLaneEnabled) {\n    logger.debug('🚫 泳道功能未启用，跳过服务注销');\n    return true;\n  }\n\n  try {\n    // 停止心跳\n    stopHeartbeat();\n\n    // 构建注销请求\n    const deregistrationUrl = `${config.nacosUrl}/nacos/v1/ns/instance`;\n    const params = new URLSearchParams();\n    params.append('serviceName', config.serviceName);\n    params.append('ip', config.host);\n    params.append('port', port.toString());\n    params.append('ephemeral', 'true');\n\n    // 发送注销请求\n    logger.debug(`📤 发送注销请求到 Nacos: ${deregistrationUrl}`);\n\n    const response = await axios.delete(`${deregistrationUrl}?${params.toString()}`, {\n      timeout: config.registrationTimeout,\n    });\n\n    // 记录响应结果\n    logger.debug(`📥 注销响应状态码: ${response.status}, 数据: ${JSON.stringify(response.data)}`);\n\n    if (response.status === 200 && response.data === 'ok') {\n      logger.success(`✅ 服务注销成功: ${config.serviceName}@${config.host}:${port}`);\n\n      // 更新全局状态\n      const globalState = getGlobalState();\n      globalState._laneMgrRegistered = false;\n      globalState._laneMgrPort = undefined;\n\n      return true;\n    } else {\n      logger.error(`❌ 服务注销失败: ${response.data}`);\n      return false;\n    }\n  } catch (error) {\n    logger.error(`❌ 服务注销错误: ${error instanceof Error ? error.message : String(error)}`);\n    return false;\n  }\n}\n\n/**\n * 发送心跳到 Nacos\n * 定期向 Nacos 发送心跳，保持服务实例的活跃状态\n *\n * @param port 服务端口\n * @param logDetails 是否打印详细日志，默认为 false\n * @returns 心跳是否成功\n */\nexport async function sendHeartbeat(port: number, logDetails: boolean = false): Promise<boolean> {\n  const config = getConfig();\n\n  // 检查泳道功能是否启用\n  if (!config.isLaneEnabled) {\n    if (logDetails) {\n      logger.debug('🚫 泳道功能未启用，跳过心跳');\n    }\n    return true;\n  }\n\n  try {\n    // 构建心跳请求\n    const heartbeatUrl = `${config.nacosUrl}/nacos/v1/ns/instance/beat`;\n    const params = new URLSearchParams();\n    params.append('serviceName', config.serviceName);\n    params.append('ip', config.host);\n    params.append('port', port.toString());\n\n    // 构建心跳数据\n    const now = new Date();\n    const beat = {\n      serviceName: config.serviceName,\n      ip: config.host,\n      port: port,\n      weight: 1.0,\n      metadata: {\n        ...config.metadata,\n        lastHeartbeat: now.toISOString(), // 添加心跳时间戳\n        heartbeatTimestamp: now.getTime().toString(), // 添加时间戳（毫秒）\n      },\n      cluster: config.currentLaneId,\n      scheduled: false\n    };\n\n    params.append('beat', JSON.stringify(beat));\n\n    // 发送心跳请求（只在需要时打印日志）\n    if (logDetails) {\n      logger.debug(`💓 发送心跳到 Nacos: ${heartbeatUrl}`);\n    }\n\n    const response = await axios.put(`${heartbeatUrl}?${params.toString()}`, null, {\n      headers: {\n        'User-Agent': 'Nuxt3-LaneManager/1.0',\n      },\n      timeout: config.registrationTimeout / 2, // 心跳超时时间应该比注册短\n    });\n\n    // 记录响应结果（只在需要时打印日志）\n    if (logDetails) {\n      logger.debug(`📥 心跳响应状态码: ${response.status}, 数据: ${JSON.stringify(response.data)}`);\n    }\n\n    if (response.status === 200) {\n      if (logDetails) {\n        logger.debug(`✅ 心跳成功: ${config.serviceName}@${config.host}:${port}`);\n      }\n      return true;\n    } else {\n      // 失败总是打印日志，无论 logDetails 如何设置\n      logger.warn(`⚠️ 心跳失败: ${response.data}`);\n      return false;\n    }\n  } catch (error) {\n    logger.error(`❌ 心跳错误: ${error instanceof Error ? error.message : String(error)}`);\n    return false;\n  }\n}\n\n/**\n * 启动心跳定时器\n * 创建一个定时器，定期向 Nacos 发送心跳\n *\n * @param port 服务端口\n */\nexport function startHeartbeat(port: number): void {\n  const config = getConfig();\n  const globalState = getGlobalState();\n\n  // 如果已经有心跳定时器，先停止\n  stopHeartbeat();\n\n  // 初始化心跳计数器\n  globalState._laneMgrHeartbeatCount = 0;\n\n  // 创建新的心跳定时器\n  logger.info(`⏱️ 启动心跳定时器，间隔: ${config.heartbeatInterval}毫秒，每30次心跳打印一次日志`);\n\n  globalState._laneMgrHeartbeatTimer = setInterval(async () => {\n    try {\n      // 增加心跳计数器\n      if (globalState._laneMgrHeartbeatCount !== undefined) {\n        globalState._laneMgrHeartbeatCount++;\n      } else {\n        globalState._laneMgrHeartbeatCount = 1;\n      }\n\n      // 是否打印详细日志（每30次打印一次）\n      const shouldLogDetails = globalState._laneMgrHeartbeatCount % 30 === 0;\n\n      // 发送心跳\n      await sendHeartbeat(port, shouldLogDetails);\n\n      // 如果达到30次，在日志中显示计数器状态\n      if (shouldLogDetails) {\n        logger.info(`💓 心跳计数: ${globalState._laneMgrHeartbeatCount}，继续保持连接...`);\n      }\n    } catch (error) {\n      logger.error(`❌ 心跳定时器错误: ${error instanceof Error ? error.message : String(error)}`);\n    }\n  }, config.heartbeatInterval);\n}\n\n/**\n * 停止心跳定时器\n * 清除心跳定时器，通常在服务注销时调用\n */\nexport function stopHeartbeat(): void {\n  const globalState = getGlobalState();\n\n  if (globalState._laneMgrHeartbeatTimer) {\n    logger.info('⏹️ 停止心跳定时器');\n    clearInterval(globalState._laneMgrHeartbeatTimer);\n    globalState._laneMgrHeartbeatTimer = undefined;\n    globalState._laneMgrHeartbeatCount = 0; // 重置心跳计数器\n  }\n}\n\n/**\n * 从 Nacos 获取指定泳道的健康服务实例\n * 查询 Nacos 获取指定服务名称和泳道 ID 的健康实例列表\n * 支持按心跳时间排序，优先选择最近心跳的实例\n *\n * @param serviceName 服务名称\n * @param targetLaneId 目标泳道ID\n * @param sortByHeartbeat 是否按心跳时间排序（最近心跳的在前）\n * @returns 健康服务实例列表\n */\nexport async function getNacosLaneInstances(\n  serviceName: string,\n  targetLaneId: string,\n  sortByHeartbeat: boolean = true\n): Promise<ServiceInstanceInfo[]> {\n  const config = getConfig();\n\n  // 使用 console.log 确保日志一定会输出\n  console.log(`[multi-lane-manager] 🔍 获取 Nacos 实例，服务名: ${serviceName}, 目标泳道: ${targetLaneId}`);\n  logger.debug(`🔍 获取 Nacos 实例，服务名: ${serviceName}, 目标泳道: ${targetLaneId}`);\n\n  try {\n    // 构建查询 URL\n    const nacosListUrl = `${config.nacosUrl}/nacos/v1/ns/instance/list`;\n\n    // 设置查询参数\n    const params = new URLSearchParams({\n      serviceName,\n      healthyOnly: 'true', // 只获取健康实例\n      groupName: config.nacosGroupName,\n    });\n\n    // 添加命名空间参数（如果有）\n    if (config.nacosNamespace) {\n      params.append('namespaceId', config.nacosNamespace);\n    }\n\n    logger.debug(`📤 Nacos 实例查询 URL: ${nacosListUrl}?${params.toString()}`);\n\n    // 发送查询请求\n    const response = await axios.get<NacosServiceListResponse>(`${nacosListUrl}?${params.toString()}`, {\n      timeout: config.registrationTimeout,\n    });\n\n    logger.debug(`📥 Nacos 实例查询响应状态: ${response.status}`);\n\n    // 处理响应数据\n    if (response.data && response.data.hosts) {\n      // 过滤出目标泳道的健康实例\n      const filteredInstances = response.data.hosts\n        .filter(\n          (instance) =>\n            instance.healthy && instance.enabled && instance.metadata && instance.metadata.laneId === targetLaneId,\n        )\n        .map(\n          (instance): ServiceInstanceInfo => {\n            // 尝试从元数据中获取最后心跳时间\n            let lastHeartbeat = Date.now();\n\n            // 检查实例元数据中是否有心跳时间信息\n            if (instance.metadata?.heartbeatTimestamp) {\n              // 优先使用数字时间戳（毫秒）\n              try {\n                const timestamp = parseInt(instance.metadata.heartbeatTimestamp, 10);\n                if (!isNaN(timestamp) && timestamp > 0) {\n                  lastHeartbeat = timestamp;\n                }\n              } catch (error) {\n                logger.debug(`⚠️ 解析实例 ${instance.ip}:${instance.port} 数字时间戳失败: ${error}`);\n              }\n            } else if (instance.metadata?.lastHeartbeat) {\n              // 备选：使用ISO字符串时间戳\n              try {\n                const heartbeatTime = new Date(instance.metadata.lastHeartbeat).getTime();\n                if (!isNaN(heartbeatTime)) {\n                  lastHeartbeat = heartbeatTime;\n                }\n              } catch (error) {\n                logger.debug(`⚠️ 解析实例 ${instance.ip}:${instance.port} ISO时间戳失败: ${error}`);\n              }\n            }\n\n            // 如果Nacos返回了实例的心跳间隔信息，可以估算最后心跳时间\n            if (instance.instanceHeartBeatInterval && !instance.metadata?.lastHeartbeat) {\n              // 使用当前时间减去心跳间隔的一半作为估算值\n              lastHeartbeat = Date.now() - (instance.instanceHeartBeatInterval / 2);\n            }\n\n            return {\n              ip: instance.ip,\n              port: instance.port,\n              serviceName: instance.serviceName,\n              clusterName: instance.clusterName,\n              ephemeral: instance.ephemeral,\n              metadata: instance.metadata,\n              status: 'UP',\n              lastHeartbeat,\n              version: instance.metadata?.version || 'unknown',\n            };\n          },\n        );\n\n      // 如果需要按心跳时间排序\n      if (sortByHeartbeat) {\n        filteredInstances.sort((a, b) => {\n          // 按最后心跳时间降序排列（最近心跳的在前）\n          const timeA = typeof a.lastHeartbeat === 'number' ? a.lastHeartbeat : new Date(a.lastHeartbeat).getTime();\n          const timeB = typeof b.lastHeartbeat === 'number' ? b.lastHeartbeat : new Date(b.lastHeartbeat).getTime();\n          return timeB - timeA;\n        });\n\n        logger.debug(`🔄 已按心跳时间排序 ${filteredInstances.length} 个实例`);\n\n        // 在调试模式下输出排序后的实例信息\n        if (filteredInstances.length > 0) {\n          logger.debug(`📊 实例心跳时间排序结果:`);\n          filteredInstances.forEach((instance, index) => {\n            const heartbeatTime = typeof instance.lastHeartbeat === 'number'\n              ? new Date(instance.lastHeartbeat).toISOString()\n              : instance.lastHeartbeat;\n            logger.debug(`  ${index + 1}. ${instance.ip}:${instance.port} - 心跳时间: ${heartbeatTime}`);\n          });\n        }\n      }\n\n      logger.info(`✅ 成功查询到 ${filteredInstances.length} 个属于泳道 ${targetLaneId} 的健康实例${sortByHeartbeat ? '（已按心跳时间排序）' : ''}`);\n      return filteredInstances;\n    } else {\n      logger.warn(`⚠️ Nacos 实例查询响应格式不正确或无实例列表:`, response.data);\n      return [];\n    }\n  } catch (error) {\n    logger.error(`❌ Nacos 实例查询失败: ${error instanceof Error ? error.message : String(error)}`);\n    if (axios.isAxiosError(error) && error.response) {\n      logger.error(`🔴 HTTP状态码: ${error.response.status}, 响应: ${JSON.stringify(error.response.data)}`);\n    }\n    return [];\n  }\n}\n"],"mappings":"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","names":[]}