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 }