136 lines
3.8 KiB
Go
136 lines
3.8 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"time"
|
|
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// BandwidthDetectionService gère la détection de bande passante réseau
|
|
// T0347: Create Network Bandwidth Detection Service
|
|
type BandwidthDetectionService struct {
|
|
samples []int64
|
|
maxSamples int
|
|
mutex sync.RWMutex
|
|
logger *zap.Logger
|
|
}
|
|
|
|
// NewBandwidthDetectionService crée un nouveau service de détection de bande passante
|
|
func NewBandwidthDetectionService(logger *zap.Logger) *BandwidthDetectionService {
|
|
if logger == nil {
|
|
logger = zap.NewNop()
|
|
}
|
|
return &BandwidthDetectionService{
|
|
samples: make([]int64, 0, 10),
|
|
maxSamples: 10,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
// MeasureBandwidth mesure la bande passante en bps (bits per second)
|
|
// bytesTransferred: nombre d'octets transférés
|
|
// duration: durée du transfert
|
|
// Retourne la moyenne de bande passante en bps
|
|
func (s *BandwidthDetectionService) MeasureBandwidth(ctx context.Context, bytesTransferred int64, duration time.Duration) int64 {
|
|
if duration <= 0 {
|
|
s.logger.Warn("Invalid duration for bandwidth measurement", zap.Duration("duration", duration))
|
|
return 0
|
|
}
|
|
|
|
if bytesTransferred < 0 {
|
|
s.logger.Warn("Invalid bytes transferred for bandwidth measurement", zap.Int64("bytes", bytesTransferred))
|
|
return 0
|
|
}
|
|
|
|
// Calculer la bande passante en bps (bits per second)
|
|
// bytesTransferred * 8 pour convertir en bits
|
|
// duration.Seconds() pour obtenir la durée en secondes
|
|
seconds := duration.Seconds()
|
|
if seconds <= 0 {
|
|
return 0
|
|
}
|
|
|
|
// Utiliser float64 pour éviter les problèmes de précision avec les durées très courtes
|
|
bandwidth := int64((float64(bytesTransferred) * 8.0) / seconds)
|
|
|
|
s.mutex.Lock()
|
|
defer s.mutex.Unlock()
|
|
|
|
// Ajouter l'échantillon
|
|
s.samples = append(s.samples, bandwidth)
|
|
|
|
// Limiter le nombre d'échantillons
|
|
if len(s.samples) > s.maxSamples {
|
|
s.samples = s.samples[1:]
|
|
}
|
|
|
|
// Calculer et retourner la moyenne
|
|
return s.calculateAverage()
|
|
}
|
|
|
|
// calculateAverage calcule la moyenne des échantillons de bande passante
|
|
func (s *BandwidthDetectionService) calculateAverage() int64 {
|
|
if len(s.samples) == 0 {
|
|
return 0
|
|
}
|
|
|
|
var sum int64
|
|
for _, sample := range s.samples {
|
|
sum += sample
|
|
}
|
|
|
|
return sum / int64(len(s.samples))
|
|
}
|
|
|
|
// GetAverageBandwidth retourne la moyenne actuelle de bande passante sans ajouter de nouvel échantillon
|
|
func (s *BandwidthDetectionService) GetAverageBandwidth() int64 {
|
|
s.mutex.RLock()
|
|
defer s.mutex.RUnlock()
|
|
return s.calculateAverage()
|
|
}
|
|
|
|
// RecommendBitrate recommande un bitrate optimal en kbps basé sur la bande passante disponible
|
|
// bandwidth: bande passante en bps (bits per second)
|
|
// Retourne le bitrate recommandé en kbps
|
|
func (s *BandwidthDetectionService) RecommendBitrate(bandwidth int64) int {
|
|
if bandwidth <= 0 {
|
|
// Par défaut, retourner le bitrate le plus bas
|
|
return 128
|
|
}
|
|
|
|
// Réserver 20% de buffer pour éviter les problèmes de réseau
|
|
available := float64(bandwidth) * 0.8
|
|
|
|
// Convertir en kbps pour la comparaison
|
|
availableKbps := available / 1000.0
|
|
|
|
// Recommander le bitrate le plus élevé possible selon la bande passante disponible
|
|
// Les bitrates standards sont: 128, 192, 320 kbps
|
|
if availableKbps >= 320 {
|
|
return 320
|
|
} else if availableKbps >= 192 {
|
|
return 192
|
|
} else if availableKbps >= 128 {
|
|
return 128
|
|
}
|
|
|
|
// Si la bande passante est très faible, retourner quand même 128 kbps
|
|
// (le client devra gérer la mise en buffer)
|
|
return 128
|
|
}
|
|
|
|
// ClearSamples efface tous les échantillons de bande passante
|
|
func (s *BandwidthDetectionService) ClearSamples() {
|
|
s.mutex.Lock()
|
|
defer s.mutex.Unlock()
|
|
s.samples = make([]int64, 0, s.maxSamples)
|
|
}
|
|
|
|
// GetSampleCount retourne le nombre d'échantillons actuels
|
|
func (s *BandwidthDetectionService) GetSampleCount() int {
|
|
s.mutex.RLock()
|
|
defer s.mutex.RUnlock()
|
|
return len(s.samples)
|
|
}
|