use ttlcache (#2677)

* use ttlcache

* go

* test
This commit is contained in:
Paul Wells
2024-04-23 02:20:54 -07:00
committed by GitHub
parent f239f8bff1
commit c51b3e3fe2
6 changed files with 64 additions and 86 deletions

1
go.mod
View File

@@ -16,6 +16,7 @@ require (
github.com/gorilla/websocket v1.5.1
github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/golang-lru/v2 v2.0.7
github.com/jellydator/ttlcache/v3 v3.2.0
github.com/jxskiss/base62 v1.1.0
github.com/livekit/mageutil v0.0.0-20230125210925-54e8a70427c1
github.com/livekit/mediatransportutil v0.0.0-20240416023643-881d3dc5423e

2
go.sum
View File

@@ -85,6 +85,8 @@ github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+l
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/jellydator/ttlcache/v3 v3.2.0 h1:6lqVJ8X3ZaUwvzENqPAobDsXNExfUJd61u++uW8a3LE=
github.com/jellydator/ttlcache/v3 v3.2.0/go.mod h1:hi7MGFdMAwZna5n2tuvh63DvFLzVKySzCVW6+0gA2n4=
github.com/josharian/native v0.0.0-20200817173448-b6b71def0850/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=

View File

@@ -504,7 +504,7 @@ func (r *RoomManager) StartSession(
}
})
participant.OnICEConfigChanged(func(participant types.LocalParticipant, iceConfig *livekit.ICEConfig) {
r.iceConfigCache.Put(iceConfigCacheKey{roomName, participant.Identity()}, iceConfig, time.Now())
r.iceConfigCache.Put(iceConfigCacheKey{roomName, participant.Identity()}, iceConfig)
})
go r.rtcSessionWorker(room, participant, requestSource)

View File

@@ -1,85 +0,0 @@
package utils
import (
"sync"
"time"
"github.com/livekit/protocol/livekit"
"go.uber.org/atomic"
)
const (
iceConfigTTLMin = 5 * time.Minute
)
type iceConfigCacheEntry struct {
iceConfig *livekit.ICEConfig
modifiedAt time.Time
}
type IceConfigCache[T comparable] struct {
lock sync.Mutex
ttl time.Duration
entries map[T]*iceConfigCacheEntry
stopped atomic.Bool
}
func NewIceConfigCache[T comparable](ttl time.Duration) *IceConfigCache[T] {
icc := &IceConfigCache[T]{
entries: make(map[T]*iceConfigCacheEntry),
}
if ttl < iceConfigTTLMin {
icc.ttl = iceConfigTTLMin
} else {
icc.ttl = ttl
}
go icc.pruneWorker()
return icc
}
func (icc *IceConfigCache[T]) Stop() {
icc.stopped.Store(true)
}
func (icc *IceConfigCache[T]) Put(key T, iceConfig *livekit.ICEConfig, at time.Time) {
icc.lock.Lock()
defer icc.lock.Unlock()
icc.entries[key] = &iceConfigCacheEntry{
iceConfig: iceConfig,
modifiedAt: at,
}
}
func (icc *IceConfigCache[T]) Get(key T) *livekit.ICEConfig {
icc.lock.Lock()
defer icc.lock.Unlock()
entry, ok := icc.entries[key]
if !ok || time.Since(entry.modifiedAt) > icc.ttl {
delete(icc.entries, key)
return &livekit.ICEConfig{}
}
return entry.iceConfig
}
func (icc *IceConfigCache[T]) pruneWorker() {
ticker := time.NewTicker(icc.ttl / 2)
defer ticker.Stop()
for !icc.stopped.Load() {
<-ticker.C
icc.lock.Lock()
for key, entry := range icc.entries {
if time.Since(entry.modifiedAt) > icc.ttl {
delete(icc.entries, key)
}
}
icc.lock.Unlock()
}
}

View File

@@ -0,0 +1,42 @@
package utils
import (
"time"
"github.com/jellydator/ttlcache/v3"
"github.com/livekit/protocol/livekit"
)
const (
iceConfigTTLMin = 5 * time.Minute
)
type IceConfigCache[T comparable] struct {
c *ttlcache.Cache[T, *livekit.ICEConfig]
}
func NewIceConfigCache[T comparable](ttl time.Duration) *IceConfigCache[T] {
cache := ttlcache.New(
ttlcache.WithTTL[T, *livekit.ICEConfig](max(ttl, iceConfigTTLMin)),
ttlcache.WithDisableTouchOnHit[T, *livekit.ICEConfig](),
)
go cache.Start()
return &IceConfigCache[T]{cache}
}
func (icc *IceConfigCache[T]) Stop() {
icc.c.Stop()
}
func (icc *IceConfigCache[T]) Put(key T, iceConfig *livekit.ICEConfig) {
icc.c.Set(key, iceConfig, ttlcache.DefaultTTL)
}
func (icc *IceConfigCache[T]) Get(key T) *livekit.ICEConfig {
if it := icc.c.Get(key); it != nil {
return it.Value()
}
return &livekit.ICEConfig{}
}

View File

@@ -0,0 +1,18 @@
package utils
import (
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/livekit/protocol/livekit"
)
func TestIceConfigCache(t *testing.T) {
cache := NewIceConfigCache[string](10 * time.Second)
t.Cleanup(cache.Stop)
cache.Put("test", &livekit.ICEConfig{})
require.NotNil(t, cache)
}