UNPKG

consul-resolver

Version:

A load balancer for Consul services with Redis-based metrics

93 lines (92 loc) 3.58 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.weightedSrvRecordSelection = exports.roundRobinSrvSelection = exports.weightedRandomSelection = exports.leastConnectionSelection = exports.roundRobinSelection = void 0; function roundRobinSelection(services, currentIndex) { const healthyServices = services.filter((service) => service.Checks.every((check) => check.Status === "passing")); if (healthyServices.length === 0) { throw new Error("No healthy services available"); } const service = healthyServices[currentIndex % healthyServices.length]; const nextIndex = (currentIndex + 1) % healthyServices.length; return { id: service.Service.ID, service, nextIndex, }; } exports.roundRobinSelection = roundRobinSelection; function leastConnectionSelection(services, metrics, defaultMetrics) { const healthyServices = services .filter((service) => service.Checks.every((check) => check.Status === "passing")) .map((service) => { const serviceMetrics = metrics.get(service.Service.ID) || defaultMetrics; return { service, connections: serviceMetrics.activeConnections || 0, }; }); if (healthyServices.length === 0) { throw new Error("No healthy services available"); } const selectedService = healthyServices.reduce((min, current) => current.connections < min.connections ? current : min); return { id: selectedService.service.Service.ID, service: selectedService.service, }; } exports.leastConnectionSelection = leastConnectionSelection; function weightedRandomSelection(rankedServices) { if (rankedServices.length === 0) { throw new Error("No services available for selection"); } const totalScore = rankedServices.reduce((sum, service) => sum + service.score, 0); if (totalScore <= 0) { return { id: rankedServices[0].id, service: rankedServices[0].service, }; } let random = Math.random() * totalScore; for (const service of rankedServices) { random -= service.score; if (random <= 0) { return { id: service.id, service: service.service, }; } } return { id: rankedServices[0].id, service: rankedServices[0].service, }; } exports.weightedRandomSelection = weightedRandomSelection; function roundRobinSrvSelection(records, currentIndex) { if (!records || records.length === 0) { return null; } const selected = records[currentIndex % records.length]; const nextIndex = (currentIndex + 1) % records.length; return { selected, nextIndex }; } exports.roundRobinSrvSelection = roundRobinSrvSelection; function weightedSrvRecordSelection(records, currentIndex) { if (!records || records.length === 0) { return null; } const hasNonZeroWeights = records.some(record => (record.weight || 0) > 0); if (!hasNonZeroWeights) { return roundRobinSrvSelection(records, currentIndex); } const totalWeight = records.reduce((sum, record) => sum + (record.weight || 1), 0); let random = Math.random() * totalWeight; for (const record of records) { random -= (record.weight || 1); if (random <= 0) { return { selected: record, nextIndex: currentIndex }; } } return { selected: records[0], nextIndex: currentIndex }; } exports.weightedSrvRecordSelection = weightedSrvRecordSelection;