diff --git a/internal/op/movie.go b/internal/op/movie.go index 1db9e2b..8c87c9f 100644 --- a/internal/op/movie.go +++ b/internal/op/movie.go @@ -5,7 +5,6 @@ import ( "fmt" "net/url" "sync" - "sync/atomic" "time" "github.com/go-resty/resty/v2" @@ -14,13 +13,13 @@ import ( "github.com/synctv-org/synctv/internal/settings" "github.com/synctv-org/synctv/utils" "github.com/zijiren233/gencontainer/refreshcache" - "github.com/zijiren233/gencontainer/rwmap" "github.com/zijiren233/livelib/av" "github.com/zijiren233/livelib/container/flv" "github.com/zijiren233/livelib/protocol/hls" rtmpProto "github.com/zijiren233/livelib/protocol/rtmp" "github.com/zijiren233/livelib/protocol/rtmp/core" rtmps "github.com/zijiren233/livelib/server" + "golang.org/x/exp/maps" ) type Movie struct { @@ -31,8 +30,9 @@ type Movie struct { } type BaseCache struct { - URL rwmap.RWMap[string, *refreshcache.RefreshCache[string]] - MPD atomic.Pointer[refreshcache.RefreshCache[*MPDCache]] + lock sync.RWMutex + url map[string]*refreshcache.RefreshCache[string] + mpd *refreshcache.RefreshCache[*MPDCache] } type MPDCache struct { @@ -41,31 +41,57 @@ type MPDCache struct { } func (b *BaseCache) Clear() { - b.MPD.Store(nil) - b.URL.Clear() + b.lock.Lock() + defer b.lock.Unlock() + b.mpd = nil + maps.Clear(b.url) } func (b *BaseCache) InitOrLoadURLCache(id string, refreshFunc func() (string, error), maxAge time.Duration) (*refreshcache.RefreshCache[string], error) { - c, loaded := b.URL.Load(id) + b.lock.RLock() + c, loaded := b.url[id] if loaded { + b.lock.RUnlock() return c, nil } + b.lock.RUnlock() + b.lock.Lock() + defer b.lock.Unlock() - c, _ = b.URL.LoadOrStore(id, refreshcache.NewRefreshCache[string](refreshFunc, maxAge)) + c, loaded = b.url[id] + if loaded { + return c, nil + } + + c = refreshcache.NewRefreshCache[string](refreshFunc, maxAge) + b.url[id] = c return c, nil } func (b *BaseCache) InitOrLoadMPDCache(refreshFunc func() (*MPDCache, error), maxAge time.Duration) (*refreshcache.RefreshCache[*MPDCache], error) { - c := b.MPD.Load() - if c != nil { - return c, nil + b.lock.RLock() + + if b.mpd != nil { + b.lock.RUnlock() + return b.mpd, nil } + b.lock.RUnlock() + b.lock.Lock() + defer b.lock.Unlock() - c = refreshcache.NewRefreshCache[*MPDCache](refreshFunc, maxAge) - if b.MPD.CompareAndSwap(nil, c) { - return c, nil - } else { - return b.InitOrLoadMPDCache(refreshFunc, maxAge) + if b.mpd != nil { + return b.mpd, nil + } + + b.mpd = refreshcache.NewRefreshCache[*MPDCache](refreshFunc, maxAge) + return b.mpd, nil +} + +func (m *Movie) Clone() *Movie { + return &Movie{ + Movie: m.Movie, + channel: m.channel, + cache: m.cache, } } diff --git a/internal/op/room.go b/internal/op/room.go index a64e711..c4035d1 100644 --- a/internal/op/room.go +++ b/internal/op/room.go @@ -177,6 +177,7 @@ func (r *Room) GetMovieByID(id string) (*Movie, error) { func (r *Room) Current() *Current { c := r.current.Current() + c.Movie = c.Movie.Clone() return &c } diff --git a/server/handlers/movie.go b/server/handlers/movie.go index 8a2464b..762aee2 100644 --- a/server/handlers/movie.go +++ b/server/handlers/movie.go @@ -580,7 +580,9 @@ func proxyURL(ctx *gin.Context, u string, headers map[string]string) error { return errors.New("not allow proxy to local") } } - req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil) + ctx2, cf := context.WithCancel(ctx) + defer cf() + req, err := http.NewRequestWithContext(ctx2, http.MethodGet, u, nil) if err != nil { return err }