68 lines
1.4 KiB
Go
68 lines
1.4 KiB
Go
package gateway
|
|
|
|
import (
|
|
"context"
|
|
"sync/atomic"
|
|
"time"
|
|
)
|
|
|
|
type Metrics struct {
|
|
ActiveSessions atomic.Int64
|
|
AdmissionRejects atomic.Uint64
|
|
MediaDrops atomic.Uint64
|
|
ProviderErrors atomic.Uint64
|
|
InputRejected atomic.Uint64
|
|
}
|
|
|
|
type MetricsSnapshot struct {
|
|
ActiveSessions int64
|
|
AdmissionRejects uint64
|
|
MediaDrops uint64
|
|
ProviderErrors uint64
|
|
InputRejected uint64
|
|
}
|
|
|
|
func (m *Metrics) Snapshot() MetricsSnapshot {
|
|
return MetricsSnapshot{
|
|
ActiveSessions: m.ActiveSessions.Load(),
|
|
AdmissionRejects: m.AdmissionRejects.Load(),
|
|
MediaDrops: m.MediaDrops.Load(),
|
|
ProviderErrors: m.ProviderErrors.Load(),
|
|
InputRejected: m.InputRejected.Load(),
|
|
}
|
|
}
|
|
|
|
type Pacer struct {
|
|
bytesPerSecond int64
|
|
last time.Time
|
|
}
|
|
|
|
func NewPacer(kbps int64) *Pacer {
|
|
if kbps < 1 {
|
|
return &Pacer{}
|
|
}
|
|
return &Pacer{bytesPerSecond: kbps * 1000 / 8}
|
|
}
|
|
|
|
func (p *Pacer) Wait(ctx context.Context, bytes int) error {
|
|
if p.bytesPerSecond < 1 || bytes < 1 {
|
|
return nil
|
|
}
|
|
now := time.Now()
|
|
if p.last.IsZero() || now.After(p.last) {
|
|
p.last = now
|
|
}
|
|
delay := time.Duration(float64(bytes) / float64(p.bytesPerSecond) * float64(time.Second))
|
|
p.last = p.last.Add(delay)
|
|
if wait := time.Until(p.last); wait > 0 {
|
|
timer := time.NewTimer(wait)
|
|
defer timer.Stop()
|
|
select {
|
|
case <-ctx.Done():
|
|
return ctx.Err()
|
|
case <-timer.C:
|
|
}
|
|
}
|
|
return nil
|
|
}
|