Skip redundant rescans on HELLO and speed up local full-scan indexing.

This commit is contained in:
Jos Vooges | STH 2026-08-26 03:05:06 +02:00
parent 76c989ba3c
commit 0611cb5f8c
4 changed files with 42 additions and 11 deletions

View file

@ -7,8 +7,8 @@ WORKDIR /src
RUN apk add --no-cache git ca-certificates
COPY node/media-node/ ./
RUN go mod tidy \
&& CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w -X main.version=1.2.5" -o /media-node-linux-amd64 ./cmd/media-node \
&& CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-s -w -X main.version=1.2.5" -o /media-node-linux-arm64 ./cmd/media-node
&& CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w -X main.version=1.2.6" -o /media-node-linux-amd64 ./cmd/media-node \
&& CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-s -w -X main.version=1.2.6" -o /media-node-linux-arm64 ./cmd/media-node
FROM base AS builder
COPY package.json pnpm-workspace.yaml ./

View file

@ -24,7 +24,7 @@ import (
"github.com/sthmedia/media-node/internal/streaming"
)
var version = "1.2.5"
var version = "1.2.6"
func main() {
if len(os.Args) < 2 {

View file

@ -283,12 +283,18 @@ func (c *Client) handleMessage(msgType string, payload json.RawMessage) {
}
log.Println("Connected to Master")
c.applyScannerSettings(ack.FullScanInterval, ack.FullScanAt, ack.FullScanIntervalSeconds)
rootsChanged := false
if len(ack.ScanRoots) > 0 {
c.applyScanRoots(ack.ScanRoots)
rootsChanged = c.applyScanRoots(ack.ScanRoots)
} else if len(ack.MoviesPaths) > 0 || len(ack.SeriesPaths) > 0 {
c.applyMediaPaths(ack.MoviesPaths, ack.SeriesPaths)
rootsChanged = true
}
// If roots changed, FullScan already started and will sync when done.
// Otherwise push current inventory (with shelfIds) to Master.
if !rootsChanged {
go c.sendFullSync()
}
case "FULL_LIBRARY_SYNC_ACK":
var p struct {
Accepted bool `json:"accepted"`
@ -418,7 +424,7 @@ func (c *Client) applyScanRoots(rows []struct {
Path string `json:"path"`
ShelfID string `json:"shelfId"`
Kind string `json:"kind"`
}) {
}) bool {
roots := make([]config.MediaRoot, 0, len(rows))
for _, r := range rows {
path := strings.TrimSpace(r.Path)
@ -434,7 +440,7 @@ func (c *Client) applyScanRoots(rows []struct {
}
roots = append(roots, config.MediaRoot{Path: path, ShelfID: r.ShelfID, Kind: kind})
}
c.scanner.UpdateMediaRoots(roots)
changed := c.scanner.UpdateMediaRoots(roots)
c.cfg.Media.Roots = roots
var movies, series []string
for _, r := range roots {
@ -446,11 +452,12 @@ func (c *Client) applyScanRoots(rows []struct {
}
c.cfg.Media.Movies = movies
c.cfg.Media.Series = series
if c.configPath != "" {
if changed && c.configPath != "" {
if err := config.Save(c.configPath, c.cfg); err != nil {
log.Printf("Failed to save media roots: %v", err)
}
}
return changed
}
func normalizePaths(in []string) []string {

View file

@ -133,8 +133,14 @@ func (s *Scanner) UpdateMediaPaths(movies, series []string) {
}
// UpdateMediaRoots replaces scan roots (with optional shelf IDs).
func (s *Scanner) UpdateMediaRoots(roots []config.MediaRoot) {
// Returns true when roots changed (and a full scan was started).
func (s *Scanner) UpdateMediaRoots(roots []config.MediaRoot) bool {
s.mu.Lock()
if mediaRootsEqual(s.cfg.Media.EffectiveRoots(), roots) {
s.mu.Unlock()
log.Printf("Media roots unchanged (%d roots) — skip rescan", len(roots))
return false
}
s.cfg.Media.Roots = append([]config.MediaRoot{}, roots...)
var movies, series []string
for _, r := range roots {
@ -151,8 +157,23 @@ func (s *Scanner) UpdateMediaRoots(roots []config.MediaRoot) {
case s.reloadWatch <- struct{}{}:
default:
}
log.Printf("Media roots updated: %d roots", len(roots))
log.Printf("Media roots updated: %d roots — starting full scan", len(roots))
go s.FullScan()
return true
}
func mediaRootsEqual(a, b []config.MediaRoot) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if filepath.Clean(a[i].Path) != filepath.Clean(b[i].Path) ||
a[i].ShelfID != b[i].ShelfID ||
a[i].Kind != b[i].Kind {
return false
}
}
return true
}
func (s *Scanner) runStartupScan() {
@ -491,7 +512,10 @@ func (s *Scanner) indexFile(path string, info os.FileInfo, eventType, preferredT
}
localFileID := database.FileID(path)
rev, _ := s.store.NextRevision()
var rev int64
if emitEvents {
rev, _ = s.store.NextRevision()
}
lf := database.LocalFile{
LocalFileID: localFileID,