Wait for full scan to finish before library sync to avoid Master pruning.
This commit is contained in:
parent
a0a6430f39
commit
68440f4081
4 changed files with 62 additions and 40 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.0" -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.1" -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.0" -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.1" -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.0"
|
var version = "1.2.1"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if len(os.Args) < 2 {
|
if len(os.Args) < 2 {
|
||||||
|
|
|
||||||
|
|
@ -614,6 +614,10 @@ func (c *Client) sendFullSync() {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// Never sync a half-built inventory — Master would prune the rest as missing.
|
||||||
|
log.Println("Waiting for scanner to finish before full library sync...")
|
||||||
|
c.scanner.WaitUntilIdle()
|
||||||
|
|
||||||
files := c.scanner.AllMediaFiles()
|
files := c.scanner.AllMediaFiles()
|
||||||
rev, _ := c.store.MaxRevision()
|
rev, _ := c.store.MaxRevision()
|
||||||
syncID := uuid.New().String()
|
syncID := uuid.New().String()
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ type Scanner struct {
|
||||||
onEvents EventHandler
|
onEvents EventHandler
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
scanning bool
|
scanning bool
|
||||||
|
rescanQueued bool
|
||||||
status string
|
status string
|
||||||
resetSchedule chan struct{}
|
resetSchedule chan struct{}
|
||||||
reloadWatch chan struct{}
|
reloadWatch chan struct{}
|
||||||
|
|
@ -69,6 +70,19 @@ func (s *Scanner) Status() string {
|
||||||
return s.status
|
return s.status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WaitUntilIdle blocks until no full scan is running or queued.
|
||||||
|
func (s *Scanner) WaitUntilIdle() {
|
||||||
|
for {
|
||||||
|
s.mu.Lock()
|
||||||
|
busy := s.scanning || s.rescanQueued
|
||||||
|
s.mu.Unlock()
|
||||||
|
if !busy {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Scanner) Start() {
|
func (s *Scanner) Start() {
|
||||||
// One inventory pass at boot, then realtime watch + scheduled catch-up.
|
// One inventory pass at boot, then realtime watch + scheduled catch-up.
|
||||||
go s.runStartupScan()
|
go s.runStartupScan()
|
||||||
|
|
@ -204,29 +218,22 @@ func nextLocalClock(now time.Time, hour, minute int) time.Time {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Scanner) FullScan() {
|
func (s *Scanner) FullScan() {
|
||||||
|
for {
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
if s.scanning {
|
if s.scanning {
|
||||||
|
s.rescanQueued = true
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.scanning = true
|
s.scanning = true
|
||||||
|
s.rescanQueued = false
|
||||||
s.status = "scanning"
|
s.status = "scanning"
|
||||||
|
roots := s.cfg.Media.EffectiveRoots()
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
|
|
||||||
defer func() {
|
|
||||||
s.mu.Lock()
|
|
||||||
s.scanning = false
|
|
||||||
s.status = "idle"
|
|
||||||
s.mu.Unlock()
|
|
||||||
}()
|
|
||||||
|
|
||||||
log.Println("Starting full media scan...")
|
log.Println("Starting full media scan...")
|
||||||
found := make(map[string]bool)
|
found := make(map[string]bool)
|
||||||
|
|
||||||
s.mu.Lock()
|
|
||||||
roots := s.cfg.Media.EffectiveRoots()
|
|
||||||
s.mu.Unlock()
|
|
||||||
|
|
||||||
for _, root := range roots {
|
for _, root := range roots {
|
||||||
kind := root.Kind
|
kind := root.Kind
|
||||||
if kind == "series" {
|
if kind == "series" {
|
||||||
|
|
@ -248,7 +255,18 @@ func (s *Scanner) FullScan() {
|
||||||
s.onEvents([]LibraryEvent{event})
|
s.onEvents([]LibraryEvent{event})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.Println("Full scan completed")
|
log.Printf("Full scan completed (%d files)", len(found))
|
||||||
|
|
||||||
|
s.mu.Lock()
|
||||||
|
s.scanning = false
|
||||||
|
s.status = "idle"
|
||||||
|
again := s.rescanQueued
|
||||||
|
s.mu.Unlock()
|
||||||
|
if !again {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Println("Re-running full scan after path/config change...")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Scanner) walkRoot(dir, mediaType, shelfID string, found map[string]bool) {
|
func (s *Scanner) walkRoot(dir, mediaType, shelfID string, found map[string]bool) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue