Files
telecom-platform/apps/carrier-connector/internal/smdp/load_balancer.go
T
nutcas3 5fddd48994 feat: Implement revenue analytics calculation, resource performance tracking, and round-robin load balancing
- Add revenue calculation in GetRevenueAnalytics with active subscription base price aggregation
- Add date range filtering for revenue analytics with StartDate and EndDate support
- Add per-plan revenue, subscription count, and average revenue calculations
- Add error handling with partial result fallback for revenue queries
- Replace mock resource performance with event-based performance
2026-05-02 17:56:34 +03:00

135 lines
3.4 KiB
Go

package smdp
import (
"fmt"
"math/rand"
"time"
)
// LoadBalancer implements different load balancing strategies for carrier selection
type LoadBalancer struct {
strategy LoadBalancingStrategy
rand *rand.Rand
rrCounter uint64 // round-robin request counter
}
// LoadBalancingStrategy defines the load balancing algorithm
type LoadBalancingStrategy int
const (
StrategyRoundRobin LoadBalancingStrategy = iota
StrategyWeightedRoundRobin
StrategyLeastConnections
StrategyRandom
StrategyPriority
)
// NewLoadBalancer creates a new load balancer with default strategy
func NewLoadBalancer() *LoadBalancer {
return &LoadBalancer{
strategy: StrategyWeightedRoundRobin,
rand: rand.New(rand.NewSource(time.Now().UnixNano())),
}
}
// SelectCarrier selects the best carrier based on the configured strategy
func (lb *LoadBalancer) SelectCarrier(carriers []*Carrier, req *ProfileRequest) (*Carrier, error) {
if len(carriers) == 0 {
return nil, fmt.Errorf("no carriers available")
}
switch lb.strategy {
case StrategyRoundRobin:
return lb.roundRobinSelect(carriers), nil
case StrategyWeightedRoundRobin:
return lb.weightedRoundRobinSelect(carriers), nil
case StrategyLeastConnections:
return lb.leastConnectionsSelect(carriers), nil
case StrategyRandom:
return lb.randomSelect(carriers), nil
case StrategyPriority:
return lb.prioritySelect(carriers), nil
default:
return lb.weightedRoundRobinSelect(carriers), nil
}
}
// roundRobinSelect implements round-robin carrier selection
func (lb *LoadBalancer) roundRobinSelect(carriers []*Carrier) *Carrier {
idx := lb.rrCounter % uint64(len(carriers))
lb.rrCounter++
return carriers[idx]
}
// weightedRoundRobinSelect selects carrier based on priority and health
func (lb *LoadBalancer) weightedRoundRobinSelect(carriers []*Carrier) *Carrier {
// Calculate weights based on priority and success rate
var totalWeight int
weights := make([]int, len(carriers))
for i, carrier := range carriers {
weight := carrier.Priority
// Adjust weight based on success rate
if carrier.Metrics.TotalRequests > 0 {
successRate := float64(carrier.Metrics.SuccessfulRequests) / float64(carrier.Metrics.TotalRequests)
weight = int(float64(weight) * successRate)
}
weights[i] = weight
totalWeight += weight
}
if totalWeight == 0 {
return carriers[0]
}
// Select carrier based on weighted random
random := lb.rand.Intn(totalWeight)
currentWeight := 0
for i, weight := range weights {
currentWeight += weight
if random < currentWeight {
return carriers[i]
}
}
return carriers[0]
}
// leastConnectionsSelect selects carrier with least current load
func (lb *LoadBalancer) leastConnectionsSelect(carriers []*Carrier) *Carrier {
bestCarrier := carriers[0]
minLoad := bestCarrier.Metrics.RequestRate
for _, carrier := range carriers[1:] {
if carrier.Metrics.RequestRate < minLoad {
bestCarrier = carrier
minLoad = carrier.Metrics.RequestRate
}
}
return bestCarrier
}
// randomSelect selects a random carrier
func (lb *LoadBalancer) randomSelect(carriers []*Carrier) *Carrier {
return carriers[lb.rand.Intn(len(carriers))]
}
// prioritySelect selects carrier with highest priority
func (lb *LoadBalancer) prioritySelect(carriers []*Carrier) *Carrier {
bestCarrier := carriers[0]
highestPriority := bestCarrier.Priority
for _, carrier := range carriers[1:] {
if carrier.Priority > highestPriority {
bestCarrier = carrier
highestPriority = carrier.Priority
}
}
return bestCarrier
}