Fix race condition on info retrival

This commit is contained in:
Zoe Roux 2024-03-24 22:23:04 +01:00
parent be8bf53cc6
commit b08bfeceb6
No known key found for this signature in database

View File

@ -9,13 +9,12 @@ import (
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
"sync"
"github.com/zoriya/go-mediainfo" "github.com/zoriya/go-mediainfo"
) )
type MediaInfo struct { type MediaInfo struct {
// closed if the mediainfo is ready for read. open otherwise
ready <-chan struct{}
// The sha1 of the video file. // The sha1 of the video file.
Sha string `json:"sha"` Sha string `json:"sha"`
/// The internal path of the video file. /// The internal path of the video file.
@ -177,37 +176,38 @@ var SubtitleExtensions = map[string]string{
"vtt": "vtt", "vtt": "vtt",
} }
var infos = NewCMap[string, *MediaInfo]() type MICache struct {
info *MediaInfo
ready sync.WaitGroup
}
var infos = NewCMap[string, *MICache]()
func GetInfo(path string, sha string, route string) (*MediaInfo, error) { func GetInfo(path string, sha string, route string) (*MediaInfo, error) {
var err error var err error
ret, _ := infos.GetOrCreate(sha, func() *MediaInfo { ret, _ := infos.GetOrCreate(sha, func() *MICache {
readyChan := make(chan struct{}) mi := &MICache{info: &MediaInfo{Sha: sha}}
mi := &MediaInfo{ mi.ready.Add(1)
Sha: sha,
ready: readyChan,
}
go func() { go func() {
save_path := fmt.Sprintf("%s/%s/info.json", Settings.Metadata, sha) save_path := fmt.Sprintf("%s/%s/info.json", Settings.Metadata, sha)
if err := getSavedInfo(save_path, mi); err == nil { if err := getSavedInfo(save_path, mi.info); err == nil {
log.Printf("Using mediainfo cache on filesystem for %s", path) log.Printf("Using mediainfo cache on filesystem for %s", path)
close(readyChan) mi.ready.Done()
return return
} }
var val *MediaInfo var val *MediaInfo
val, err = getInfo(path, route) val, err = getInfo(path, route)
*mi = *val *mi.info = *val
mi.ready = readyChan mi.info.Sha = sha
mi.Sha = sha mi.ready.Done()
close(readyChan) saveInfo(save_path, mi.info)
saveInfo(save_path, mi)
}() }()
return mi return mi
}) })
<-ret.ready ret.ready.Wait()
return ret, err return ret.info, err
} }
func getSavedInfo[T any](save_path string, mi *T) error { func getSavedInfo[T any](save_path string, mi *T) error {