Skip redundant rescans on HELLO and speed up local full-scan indexing.
This commit is contained in:
parent
76c989ba3c
commit
0611cb5f8c
4 changed files with 42 additions and 11 deletions
|
|
@ -7,8 +7,8 @@ WORKDIR /src
|
||||||
RUN apk add --no-cache git ca-certificates
|
RUN apk add --no-cache git ca-certificates
|
||||||
COPY node/media-node/ ./
|
COPY node/media-node/ ./
|
||||||
RUN go mod tidy \
|
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=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.5" -o /media-node-linux-arm64 ./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
|
FROM base AS builder
|
||||||
COPY package.json pnpm-workspace.yaml ./
|
COPY package.json pnpm-workspace.yaml ./
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import (
|
||||||
"github.com/sthmedia/media-node/internal/streaming"
|
"github.com/sthmedia/media-node/internal/streaming"
|
||||||
)
|
)
|
||||||
|
|
||||||
var version = "1.2.5"
|
var version = "1.2.6"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if len(os.Args) < 2 {
|
if len(os.Args) < 2 {
|
||||||
|
|
|
||||||
|
|
@ -283,12 +283,18 @@ func (c *Client) handleMessage(msgType string, payload json.RawMessage) {
|
||||||
}
|
}
|
||||||
log.Println("Connected to Master")
|
log.Println("Connected to Master")
|
||||||
c.applyScannerSettings(ack.FullScanInterval, ack.FullScanAt, ack.FullScanIntervalSeconds)
|
c.applyScannerSettings(ack.FullScanInterval, ack.FullScanAt, ack.FullScanIntervalSeconds)
|
||||||
|
rootsChanged := false
|
||||||
if len(ack.ScanRoots) > 0 {
|
if len(ack.ScanRoots) > 0 {
|
||||||
c.applyScanRoots(ack.ScanRoots)
|
rootsChanged = c.applyScanRoots(ack.ScanRoots)
|
||||||
} else if len(ack.MoviesPaths) > 0 || len(ack.SeriesPaths) > 0 {
|
} else if len(ack.MoviesPaths) > 0 || len(ack.SeriesPaths) > 0 {
|
||||||
c.applyMediaPaths(ack.MoviesPaths, ack.SeriesPaths)
|
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()
|
||||||
}
|
}
|
||||||
go c.sendFullSync()
|
|
||||||
case "FULL_LIBRARY_SYNC_ACK":
|
case "FULL_LIBRARY_SYNC_ACK":
|
||||||
var p struct {
|
var p struct {
|
||||||
Accepted bool `json:"accepted"`
|
Accepted bool `json:"accepted"`
|
||||||
|
|
@ -418,7 +424,7 @@ func (c *Client) applyScanRoots(rows []struct {
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
ShelfID string `json:"shelfId"`
|
ShelfID string `json:"shelfId"`
|
||||||
Kind string `json:"kind"`
|
Kind string `json:"kind"`
|
||||||
}) {
|
}) bool {
|
||||||
roots := make([]config.MediaRoot, 0, len(rows))
|
roots := make([]config.MediaRoot, 0, len(rows))
|
||||||
for _, r := range rows {
|
for _, r := range rows {
|
||||||
path := strings.TrimSpace(r.Path)
|
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})
|
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
|
c.cfg.Media.Roots = roots
|
||||||
var movies, series []string
|
var movies, series []string
|
||||||
for _, r := range roots {
|
for _, r := range roots {
|
||||||
|
|
@ -446,11 +452,12 @@ func (c *Client) applyScanRoots(rows []struct {
|
||||||
}
|
}
|
||||||
c.cfg.Media.Movies = movies
|
c.cfg.Media.Movies = movies
|
||||||
c.cfg.Media.Series = series
|
c.cfg.Media.Series = series
|
||||||
if c.configPath != "" {
|
if changed && c.configPath != "" {
|
||||||
if err := config.Save(c.configPath, c.cfg); err != nil {
|
if err := config.Save(c.configPath, c.cfg); err != nil {
|
||||||
log.Printf("Failed to save media roots: %v", err)
|
log.Printf("Failed to save media roots: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return changed
|
||||||
}
|
}
|
||||||
|
|
||||||
func normalizePaths(in []string) []string {
|
func normalizePaths(in []string) []string {
|
||||||
|
|
|
||||||
|
|
@ -133,8 +133,14 @@ func (s *Scanner) UpdateMediaPaths(movies, series []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateMediaRoots replaces scan roots (with optional shelf IDs).
|
// 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()
|
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...)
|
s.cfg.Media.Roots = append([]config.MediaRoot{}, roots...)
|
||||||
var movies, series []string
|
var movies, series []string
|
||||||
for _, r := range roots {
|
for _, r := range roots {
|
||||||
|
|
@ -151,8 +157,23 @@ func (s *Scanner) UpdateMediaRoots(roots []config.MediaRoot) {
|
||||||
case s.reloadWatch <- struct{}{}:
|
case s.reloadWatch <- struct{}{}:
|
||||||
default:
|
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()
|
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() {
|
func (s *Scanner) runStartupScan() {
|
||||||
|
|
@ -491,7 +512,10 @@ func (s *Scanner) indexFile(path string, info os.FileInfo, eventType, preferredT
|
||||||
}
|
}
|
||||||
|
|
||||||
localFileID := database.FileID(path)
|
localFileID := database.FileID(path)
|
||||||
rev, _ := s.store.NextRevision()
|
var rev int64
|
||||||
|
if emitEvents {
|
||||||
|
rev, _ = s.store.NextRevision()
|
||||||
|
}
|
||||||
|
|
||||||
lf := database.LocalFile{
|
lf := database.LocalFile{
|
||||||
LocalFileID: localFileID,
|
LocalFileID: localFileID,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue