filebrowser/backend/files/indexingSchedule.go

121 lines
3.5 KiB
Go
Raw Normal View History

2024-11-26 17:21:41 +00:00
package files
import (
"log"
"time"
"github.com/gtsteffaniak/filebrowser/settings"
)
// schedule in minutes
var scanSchedule = []time.Duration{
5 * time.Minute, // 5 minute quick scan & 25 minutes for a full scan
10 * time.Minute,
20 * time.Minute, // [3] element is 20 minutes, reset anchor for full scan
40 * time.Minute,
1 * time.Hour,
2 * time.Hour,
3 * time.Hour,
4 * time.Hour, // 4 hours for quick scan & 20 hours for a full scan
}
func (si *Index) newScanner(origin string) {
fullScanAnchor := 3
fullScanCounter := 0 // every 5th scan is a full scan
for {
// Determine sleep time with modifiers
fullScanCounter++
sleepTime := scanSchedule[si.currentSchedule] + si.SmartModifier
if si.assessment == "simple" {
sleepTime = scanSchedule[si.currentSchedule] - si.SmartModifier
}
if settings.Config.Server.IndexingInterval > 0 {
sleepTime = time.Duration(settings.Config.Server.IndexingInterval) * time.Minute
}
// Log and sleep before indexing
log.Printf("Next scan in %v\n", sleepTime)
time.Sleep(sleepTime)
si.scannerMu.Lock()
if fullScanCounter == 5 {
si.RunIndexing(origin, false) // Full scan
fullScanCounter = 0
} else {
si.RunIndexing(origin, true) // Quick scan
}
si.scannerMu.Unlock()
// Adjust schedule based on file changes
if si.FilesChangedDuringIndexing {
// Move to at least the full-scan anchor or reduce interval
if si.currentSchedule > fullScanAnchor {
si.currentSchedule = fullScanAnchor
} else if si.currentSchedule > 0 {
si.currentSchedule--
}
} else {
// Increment toward the longest interval if no changes
if si.currentSchedule < len(scanSchedule)-1 {
si.currentSchedule++
}
}
if si.assessment == "simple" && si.currentSchedule > 3 {
si.currentSchedule = 3
}
// Ensure `currentSchedule` stays within bounds
if si.currentSchedule < 0 {
si.currentSchedule = 0
} else if si.currentSchedule >= len(scanSchedule) {
si.currentSchedule = len(scanSchedule) - 1
}
}
}
func (si *Index) RunIndexing(origin string, quick bool) {
prevNumDirs := si.NumDirs
prevNumFiles := si.NumFiles
if quick {
log.Println("Starting quick scan")
} else {
log.Println("Starting full scan")
si.NumDirs = 0
si.NumFiles = 0
}
startTime := time.Now()
si.FilesChangedDuringIndexing = false
// Perform the indexing operation
err := si.indexDirectory("/", quick, true)
if err != nil {
log.Printf("Error during indexing: %v", err)
}
// Update the LastIndexed time
si.LastIndexed = time.Now()
si.indexingTime = int(time.Since(startTime).Seconds())
if !quick {
// update smart indexing
if si.indexingTime < 3 || si.NumDirs < 10000 {
si.assessment = "simple"
si.SmartModifier = 4 * time.Minute
log.Println("Index is small and efficient, adjusting scan interval accordingly.")
} else if si.indexingTime > 120 || si.NumDirs > 500000 {
si.assessment = "complex"
modifier := si.indexingTime / 10 // seconds
si.SmartModifier = time.Duration(modifier) * time.Minute
log.Println("Index is large and complex, adjusting scan interval accordingly.")
} else {
si.assessment = "normal"
log.Println("Index is normal, quick scan set to every 5 minutes.")
}
log.Printf("Index assessment : complexity=%v directories=%v files=%v \n", si.assessment, si.NumDirs, si.NumFiles)
if si.NumDirs != prevNumDirs || si.NumFiles != prevNumFiles {
si.FilesChangedDuringIndexing = true
}
}
log.Printf("Time Spent Indexing : %v seconds\n", si.indexingTime)
}
func (si *Index) setupIndexingScanners() {
go si.newScanner("/")
}