Merge remote-tracking branch 'origin/master'
Some checks failed
Release / Lint and test (push) Failing after 17m48s
Release / Run Release Please (push) Has been skipped
Release / Build, tag, and publish Docker image (push) Has been skipped
Release / Notify IRC (push) Has been skipped
Nightly Release / Check latest commit (push) Successful in 9s
Nightly Release / Build and release Docker image (push) Has been skipped
Nightly Release / Lint and test (push) Has been skipped
Some checks failed
Release / Lint and test (push) Failing after 17m48s
Release / Run Release Please (push) Has been skipped
Release / Build, tag, and publish Docker image (push) Has been skipped
Release / Notify IRC (push) Has been skipped
Nightly Release / Check latest commit (push) Successful in 9s
Nightly Release / Build and release Docker image (push) Has been skipped
Nightly Release / Lint and test (push) Has been skipped
Conflicts: scanner/scanner.go
This commit is contained in:
@@ -113,7 +113,7 @@ func TestCachingParallelism(t *testing.T) {
|
||||
callback: func() { realTranscodeCount.Add(1) },
|
||||
}
|
||||
|
||||
cacheTranscoder := transcode.NewCachingTranscoder(transcoder, t.TempDir())
|
||||
cacheTranscoder := transcode.NewCachingTranscoder(transcoder, t.TempDir(), 1024)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < 5; i++ {
|
||||
|
||||
@@ -5,9 +5,12 @@ import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const perm = 0o644
|
||||
@@ -15,16 +18,21 @@ const perm = 0o644
|
||||
type CachingTranscoder struct {
|
||||
cachePath string
|
||||
transcoder Transcoder
|
||||
limitMB int
|
||||
locks keyedMutex
|
||||
cleanLock sync.RWMutex
|
||||
}
|
||||
|
||||
var _ Transcoder = (*CachingTranscoder)(nil)
|
||||
|
||||
func NewCachingTranscoder(t Transcoder, cachePath string) *CachingTranscoder {
|
||||
return &CachingTranscoder{transcoder: t, cachePath: cachePath}
|
||||
func NewCachingTranscoder(t Transcoder, cachePath string, limitMB int) *CachingTranscoder {
|
||||
return &CachingTranscoder{transcoder: t, cachePath: cachePath, limitMB: limitMB}
|
||||
}
|
||||
|
||||
func (t *CachingTranscoder) Transcode(ctx context.Context, profile Profile, in string, out io.Writer) error {
|
||||
t.cleanLock.RLock()
|
||||
defer t.cleanLock.RUnlock()
|
||||
|
||||
// don't try cache partial transcodes
|
||||
if profile.Seek() > 0 {
|
||||
return t.transcoder.Transcode(ctx, profile, in, out)
|
||||
@@ -52,6 +60,7 @@ func (t *CachingTranscoder) Transcode(ctx context.Context, profile Profile, in s
|
||||
|
||||
if i, err := cf.Stat(); err == nil && i.Size() > 0 {
|
||||
_, _ = io.Copy(out, cf)
|
||||
_ = os.Chtimes(path, time.Now(), time.Now()) // Touch for LRU cache purposes
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -64,6 +73,55 @@ func (t *CachingTranscoder) Transcode(ctx context.Context, profile Profile, in s
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *CachingTranscoder) CacheEject() error {
|
||||
t.cleanLock.Lock()
|
||||
defer t.cleanLock.Unlock()
|
||||
|
||||
// Delete LRU cache files that exceed size limit. Use last modified time.
|
||||
type file struct {
|
||||
path string
|
||||
info os.FileInfo
|
||||
}
|
||||
|
||||
var files []file
|
||||
var total int64 = 0
|
||||
|
||||
err := filepath.WalkDir(t.cachePath, func(path string, de fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !de.IsDir() {
|
||||
info, err := de.Info()
|
||||
if err != nil {
|
||||
return fmt.Errorf("walk cache path for eject: %w", err)
|
||||
}
|
||||
files = append(files, file{path, info})
|
||||
total += info.Size()
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("walk cache path for eject: %w", err)
|
||||
}
|
||||
|
||||
sort.Slice(files, func(i, j int) bool {
|
||||
return files[i].info.ModTime().Before(files[j].info.ModTime())
|
||||
})
|
||||
|
||||
for total > int64(t.limitMB)*1024*1024 {
|
||||
curFile := files[0]
|
||||
files = files[1:]
|
||||
total -= curFile.info.Size()
|
||||
err = os.Remove(curFile.path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("remove cache file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func cacheKey(cmd string, args []string) string {
|
||||
// the cache is invalid whenever transcode command (which includes the
|
||||
// absolute filepath, bit rate args, replay gain args, etc.) changes
|
||||
|
||||
Reference in New Issue
Block a user