veza/veza-backend-api/internal/services/buffer_monitor_service.go
2025-12-03 20:29:37 +01:00

128 lines
3.7 KiB
Go

package services
import (
"context"
"sync"
"go.uber.org/zap"
)
// BufferMonitorService gère le monitoring du niveau de buffer
// T0353: Create Buffer Level Monitor Service
type BufferMonitorService struct {
logger *zap.Logger
// Seuils de buffer (configurables)
lowThreshold float64 // Seuil bas (défaut: 0.2)
highThreshold float64 // Seuil haut (défaut: 0.8)
mutex sync.RWMutex
}
// NewBufferMonitorService crée un nouveau service de monitoring de buffer
func NewBufferMonitorService(logger *zap.Logger) *BufferMonitorService {
if logger == nil {
logger = zap.NewNop()
}
return &BufferMonitorService{
logger: logger,
lowThreshold: 0.2, // 20% - buffer faible
highThreshold: 0.8, // 80% - buffer élevé
}
}
// SetThresholds configure les seuils de buffer
func (s *BufferMonitorService) SetThresholds(low, high float64) {
s.mutex.Lock()
defer s.mutex.Unlock()
if low >= 0 && low <= 1 {
s.lowThreshold = low
}
if high >= 0 && high <= 1 && high > s.lowThreshold {
s.highThreshold = high
}
}
// GetThresholds retourne les seuils actuels
func (s *BufferMonitorService) GetThresholds() (low, high float64) {
s.mutex.RLock()
defer s.mutex.RUnlock()
return s.lowThreshold, s.highThreshold
}
// CalculateBufferLevel calcule le niveau de buffer (0.0 à 1.0)
// buffered: temps de contenu buffered en secondes
// duration: durée totale du contenu en secondes
// Retourne le niveau de buffer (0.0 = vide, 1.0 = plein)
func (s *BufferMonitorService) CalculateBufferLevel(buffered, duration float64) float64 {
if duration <= 0 {
s.logger.Warn("Invalid duration for buffer calculation", zap.Float64("duration", duration))
return 0.0
}
if buffered < 0 {
s.logger.Warn("Invalid buffered time for buffer calculation", zap.Float64("buffered", buffered))
return 0.0
}
// Calculer le niveau de buffer (ratio)
level := buffered / duration
// S'assurer que le niveau est entre 0.0 et 1.0
if level > 1.0 {
level = 1.0
} else if level < 0.0 {
level = 0.0
}
return level
}
// IsBufferLow vérifie si le buffer est faible
func (s *BufferMonitorService) IsBufferLow(bufferLevel float64) bool {
s.mutex.RLock()
defer s.mutex.RUnlock()
return bufferLevel < s.lowThreshold
}
// IsBufferHigh vérifie si le buffer est élevé
func (s *BufferMonitorService) IsBufferHigh(bufferLevel float64) bool {
s.mutex.RLock()
defer s.mutex.RUnlock()
return bufferLevel > s.highThreshold
}
// ShouldAdaptBuffer détermine si une adaptation est nécessaire
// Retourne true si le buffer est trop faible ou trop élevé
func (s *BufferMonitorService) ShouldAdaptBuffer(bufferLevel float64) bool {
return s.IsBufferLow(bufferLevel) || s.IsBufferHigh(bufferLevel)
}
// GetBufferStatus retourne le statut du buffer
func (s *BufferMonitorService) GetBufferStatus(bufferLevel float64) string {
if s.IsBufferLow(bufferLevel) {
return "low"
} else if s.IsBufferHigh(bufferLevel) {
return "high"
}
return "normal"
}
// MonitorBuffer surveille le niveau de buffer et détermine si une adaptation est nécessaire
// buffered: temps de contenu buffered en secondes
// duration: durée totale du contenu en secondes
// Retourne le niveau de buffer calculé et si une adaptation est nécessaire
func (s *BufferMonitorService) MonitorBuffer(ctx context.Context, buffered, duration float64) (bufferLevel float64, shouldAdapt bool, status string) {
bufferLevel = s.CalculateBufferLevel(buffered, duration)
shouldAdapt = s.ShouldAdaptBuffer(bufferLevel)
status = s.GetBufferStatus(bufferLevel)
if shouldAdapt {
s.logger.Debug("Buffer adaptation needed",
zap.Float64("buffer_level", bufferLevel),
zap.String("status", status),
zap.Float64("buffered", buffered),
zap.Float64("duration", duration))
}
return bufferLevel, shouldAdapt, status
}