fix(server): throttle events sent to UI when scanning. Relates to #1511

See also: https://github.com/navidrome/navidrome/issues/1186#issuecomment-1554818537
This commit is contained in:
Deluan
2024-09-26 18:14:00 -04:00
parent 76614b8f16
commit 80acfc103f
4 changed files with 20 additions and 6 deletions
+1
View File
@@ -51,6 +51,7 @@ require (
golang.org/x/image v0.20.0 golang.org/x/image v0.20.0
golang.org/x/sync v0.8.0 golang.org/x/sync v0.8.0
golang.org/x/text v0.18.0 golang.org/x/text v0.18.0
golang.org/x/time v0.6.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )
+2
View File
@@ -283,6 +283,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+9 -5
View File
@@ -13,6 +13,7 @@ import (
"github.com/navidrome/navidrome/model" "github.com/navidrome/navidrome/model"
"github.com/navidrome/navidrome/server/events" "github.com/navidrome/navidrome/server/events"
"github.com/navidrome/navidrome/utils/singleton" "github.com/navidrome/navidrome/utils/singleton"
"golang.org/x/time/rate"
) )
type Scanner interface { type Scanner interface {
@@ -117,7 +118,8 @@ func (s *scanner) rescan(ctx context.Context, library string, fullRescan bool) e
func (s *scanner) startProgressTracker(library string) (chan uint32, context.CancelFunc) { func (s *scanner) startProgressTracker(library string) (chan uint32, context.CancelFunc) {
// Must be a new context (not the one passed to the scan method) to allow broadcasting the scan status to all clients // Must be a new context (not the one passed to the scan method) to allow broadcasting the scan status to all clients
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
progress := make(chan uint32, 100) progress := make(chan uint32, 1000)
limiter := rate.Sometimes{Every: 10}
go func() { go func() {
s.broker.SendMessage(ctx, &events.ScanStatus{Scanning: true, Count: 0, FolderCount: 0}) s.broker.SendMessage(ctx, &events.ScanStatus{Scanning: true, Count: 0, FolderCount: 0})
defer func() { defer func() {
@@ -138,10 +140,12 @@ func (s *scanner) startProgressTracker(library string) (chan uint32, context.Can
continue continue
} }
totalFolders, totalFiles := s.incStatusCounter(library, count) totalFolders, totalFiles := s.incStatusCounter(library, count)
s.broker.SendMessage(ctx, &events.ScanStatus{ limiter.Do(func() {
Scanning: true, s.broker.SendMessage(ctx, &events.ScanStatus{
Count: int64(totalFiles), Scanning: true,
FolderCount: int64(totalFolders), Count: int64(totalFiles),
FolderCount: int64(totalFolders),
})
}) })
} }
} }
+8 -1
View File
@@ -118,7 +118,7 @@ func (s *TagScanner) Scan(ctx context.Context, lib model.Library, fullScan bool,
g, walkCtx := errgroup.WithContext(ctx) g, walkCtx := errgroup.WithContext(ctx)
g.Go(func() error { g.Go(func() error {
for folderStats := range pl.ReadOrDone(walkCtx, foldersFound) { for folderStats := range pl.ReadOrDone(walkCtx, foldersFound) {
progress <- folderStats.AudioFilesCount updateProgress(progress, folderStats.AudioFilesCount)
allFSDirs[folderStats.Path] = folderStats allFSDirs[folderStats.Path] = folderStats
if s.folderHasChanged(folderStats, allDBDirs, s.lib.LastScanAt) || fullScan { if s.folderHasChanged(folderStats, allDBDirs, s.lib.LastScanAt) || fullScan {
@@ -185,6 +185,13 @@ func (s *TagScanner) Scan(ctx context.Context, lib model.Library, fullScan bool,
return s.cnt.total(), err return s.cnt.total(), err
} }
func updateProgress(progress chan uint32, count uint32) {
select {
case progress <- count:
default: // It is ok to miss a count update
}
}
func isDirEmpty(ctx context.Context, dir string) (bool, error) { func isDirEmpty(ctx context.Context, dir string) (bool, error) {
children, stats, err := loadDir(ctx, dir) children, stats, err := loadDir(ctx, dir)
if err != nil { if err != nil {