UNPKG

@duongtrungnguyen/nestro

Version:
136 lines 5.31 kB
var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __decorateClass = (decorators, target, key, kind) => { var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target; for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result; if (kind && result) __defProp(target, key, result); return result; }; var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index); import { Injectable, Inject } from "@nestjs/common"; import { debugError, debugLog, getServerURL } from "../../common"; import { LOAD_BALANCER, LOAD_BALANCING_CONFIGS } from "../constants"; import { DiscoveryError, DiscoveryErrorCode } from "../errors"; import { ResponseTimeStrategy } from "../loadbalancing"; import { SERVER_INFO } from "../../client"; let DiscoveryService = class { constructor(loadBalancingConfigs, loadBalancer, serverInfo) { this.loadBalancingConfigs = loadBalancingConfigs; this.loadBalancer = loadBalancer; this.services = /* @__PURE__ */ new Map(); this.serverBaseUrl = getServerURL(serverInfo); } async onModuleInit() { debugLog(DiscoveryService.name, "Initializing DiscoveryService..."); await this.loadInstances(); this.refreshIntervalId = setInterval(() => this.loadInstances(), this.loadBalancingConfigs.refreshInterval); } onModuleDestroy() { if (this.refreshIntervalId) { clearInterval(this.refreshIntervalId); } debugLog(DiscoveryService.name, "DiscoveryService stopped"); } /** * Refreshes the service registry by fetching the latest instances from the server */ async loadInstances() { debugLog(DiscoveryService.name, "Refreshing service registry"); try { const response = await fetch(`${this.serverBaseUrl}/nestro/services`, { method: "GET", headers: { "Content-Type": "application/json", Accept: "application/json" } }); if (!response.ok) { throw new Error(`Failed to fetch services: ${response.statusText}`); } const services = await response.json(); this.services.clear(); Object.entries(services).forEach(([serviceName, instances]) => { const activeInstances = instances.filter((instance) => instance.status === "ON"); if (activeInstances.length > 0) { this.services.set(serviceName, activeInstances); } }); debugLog(DiscoveryService.name, `Registry refreshed with ${this.services.size} services`); } catch (error) { debugError(DiscoveryService.name, `Failed to refresh registry: ${error.message}`); } } getServices() { return this.services; } /** * Gets all instances for a specific service */ getInstances(serviceName) { return this.services.get(serviceName) || []; } async discover(serviceName, callback) { const instances = this.getInstances(serviceName); if (!instances || instances.length === 0) { throw new DiscoveryError(`Service ${serviceName} not found in registry`, DiscoveryErrorCode.SERVICE_NOT_FOUND); } let lastError = null; const attemptedInstances = /* @__PURE__ */ new Set(); const maxRetries = instances.length; for (let attempt = 0; attempt < maxRetries; attempt++) { const remainingInstances = instances.filter((instance) => !attemptedInstances.has(this.getInstanceId(instance))); if (remainingInstances.length === 0) { break; } const selectedInstance = this.loadBalancer.selectInstance(remainingInstances); if (!selectedInstance) { break; } const instanceId = this.getInstanceId(selectedInstance); attemptedInstances.add(instanceId); if (this.loadBalancer.trackConnectionStart) { this.loadBalancer.trackConnectionStart(instanceId); } const startTime = Date.now(); let shouldRetry = false; const tryAnotherInstance = async () => { attemptedInstances.add(this.getInstanceId(selectedInstance)); if (this.loadBalancer.trackConnectionEnd) { this.loadBalancer.trackConnectionEnd(instanceId); } shouldRetry = true; }; try { const result = await callback(selectedInstance, tryAnotherInstance); if (this.loadBalancer instanceof ResponseTimeStrategy) { const responseTime = Date.now() - startTime; this.loadBalancer.recordResponseTime(instanceId, responseTime); } if (!shouldRetry) { return result; } } catch (error) { if (!shouldRetry) { throw error; } } } if (lastError) throw lastError; throw new DiscoveryError(`All instances for ${serviceName} service failed`, DiscoveryErrorCode.ALL_INSTANCES_FAILED); } getInstanceId(instance) { return `${instance.name}:${instance.host}:${instance.port}`; } }; DiscoveryService = __decorateClass([ Injectable(), __decorateParam(0, Inject(LOAD_BALANCING_CONFIGS)), __decorateParam(1, Inject(LOAD_BALANCER)), __decorateParam(2, Inject(SERVER_INFO)) ], DiscoveryService); export { DiscoveryService }; //# sourceMappingURL=discovery.service.js.map