From 8a07bac2a2858faf3ea81aa519c19cd335999262 Mon Sep 17 00:00:00 2001
From: Deluan <deluan@navidrome.org>
Date: Thu, 29 Apr 2021 13:10:10 -0400
Subject: [PATCH] Fix SIGUSR1 work when ScanInterval=0

---
 cmd/root.go                       | 53 +++++++++++++++++++++++++------
 {scanner => cmd}/signaler_unix.go |  2 +-
 scanner/scanner.go                |  9 +-----
 3 files changed, 45 insertions(+), 19 deletions(-)
 rename {scanner => cmd}/signaler_unix.go (91%)

diff --git a/cmd/root.go b/cmd/root.go
index 02a2792a7..d970c9a31 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -53,8 +53,16 @@ func runNavidrome() {
 	db.EnsureLatestVersion()
 
 	var g run.Group
+
 	g.Add(startServer())
-	g.Add(startScanner())
+	g.Add(startSignaler())
+
+	interval := conf.Server.ScanInterval
+	if interval != 0 {
+		g.Add(startScanner(interval))
+	} else {
+		log.Warn("Periodic scan is DISABLED", "interval", interval)
+	}
 
 	if err := g.Run(); err != nil {
 		log.Error("Fatal error in Navidrome. Aborting", err)
@@ -76,20 +84,45 @@ func startServer() (func() error, func(err error)) {
 		}
 }
 
-func startScanner() (func() error, func(err error)) {
-	interval := conf.Server.ScanInterval
+var sigChan = make(chan os.Signal, 1)
+
+func startSignaler() (func() error, func(err error)) {
+	scanner := GetScanner()
+	ctx, cancel := context.WithCancel(context.Background())
+
+	return func() error {
+			for {
+				select {
+				case sig := <-sigChan:
+					log.Info(ctx, "Received signal, triggering a new scan", "signal", sig)
+					start := time.Now()
+					err := scanner.RescanAll(ctx, false)
+					if err != nil {
+						log.Error(ctx, "Error scanning", err)
+					}
+					log.Info(ctx, "Triggered scan complete", "elapsed", time.Since(start).Round(100*time.Millisecond))
+				case <-ctx.Done():
+					break
+				}
+			}
+		}, func(err error) {
+			cancel()
+			if err != nil {
+				log.Error("Shutting down Signaler due to error", err)
+			} else {
+				log.Info("Shutting down Signaler")
+			}
+		}
+}
+
+func startScanner(interval time.Duration) (func() error, func(err error)) {
 	log.Info("Starting scanner", "interval", interval.String())
 	scanner := GetScanner()
 	ctx, cancel := context.WithCancel(context.Background())
 
 	return func() error {
-			if interval != 0 {
-				time.Sleep(2 * time.Second) // Wait 2 seconds before the first scan
-				scanner.Run(ctx, interval)
-			} else {
-				log.Warn("Periodic scan is DISABLED", "interval", interval)
-				<-ctx.Done()
-			}
+			time.Sleep(2 * time.Second) // Wait 2 seconds before the first scan
+			scanner.Run(ctx, interval)
 
 			return nil
 		}, func(err error) {
diff --git a/scanner/signaler_unix.go b/cmd/signaler_unix.go
similarity index 91%
rename from scanner/signaler_unix.go
rename to cmd/signaler_unix.go
index cdf54acd6..919dc5bf2 100644
--- a/scanner/signaler_unix.go
+++ b/cmd/signaler_unix.go
@@ -1,7 +1,7 @@
 // +build !windows
 // +build !plan9
 
-package scanner
+package cmd
 
 import (
 	"os"
diff --git a/scanner/scanner.go b/scanner/scanner.go
index 2a3517e91..4cd569d77 100644
--- a/scanner/scanner.go
+++ b/scanner/scanner.go
@@ -4,7 +4,6 @@ import (
 	"context"
 	"errors"
 	"fmt"
-	"os"
 	"strconv"
 	"sync"
 	"time"
@@ -40,10 +39,7 @@ type FolderScanner interface {
 	Scan(ctx context.Context, lastModifiedSince time.Time, progress chan uint32) error
 }
 
-var (
-	isScanning utils.AtomicBool
-	sigChan    = make(chan os.Signal, 1)
-)
+var isScanning utils.AtomicBool
 
 type scanner struct {
 	folders     map[string]FolderScanner
@@ -87,9 +83,6 @@ func (s *scanner) Run(ctx context.Context, interval time.Duration) {
 		select {
 		case <-ticker.C:
 			continue
-		case sig := <-sigChan:
-			log.Info(ctx, "Received signal, triggering a new scan", "signal", sig)
-			continue
 		case <-ctx.Done():
 			return
 		}