Improve watcher detection and rebuild error handling

This commit is contained in:
Sky Johnson 2025-08-01 12:26:48 -05:00
parent 64dd0b0c56
commit aa340b7323
2 changed files with 86 additions and 5 deletions

View File

@ -90,7 +90,26 @@ func runWithWatcher(scriptPath string) {
fmt.Printf("Starting %s in watch mode...\n", scriptPath)
var hadError bool
firstRun := true
for {
// If we had an error on the last run and this isn't the first run,
// wait for file changes before retrying
if hadError && !firstRun {
fmt.Println("Waiting for file changes before retrying...")
select {
case <-restartCh:
fmt.Println("Files changed, retrying...")
case <-sigChan:
fmt.Println("\nExiting...")
return
}
}
firstRun = false
hadError = false
// Clear cache before each run
state.ClearCache()
@ -98,14 +117,14 @@ func runWithWatcher(scriptPath string) {
luaState, err := state.NewFromScript(scriptPath)
if err != nil {
log.Printf("Error creating state: %v", err)
time.Sleep(1 * time.Second)
hadError = true
continue
}
if err := luaState.ExecuteFile(scriptPath); err != nil {
log.Printf("Execution error: %v", err)
luaState.Close()
time.Sleep(1 * time.Second)
hadError = true
continue
}

View File

@ -2,7 +2,6 @@ package main
import (
"fmt"
"log"
"maps"
"os"
"path/filepath"
@ -13,6 +12,7 @@ import (
type FileWatcher struct {
files map[string]time.Time
dirs map[string]bool // Track watched directories
mu sync.RWMutex
restartCh chan bool
stopCh chan bool
@ -24,6 +24,7 @@ type FileWatcher struct {
func NewFileWatcher(debounceMs int) (*FileWatcher, error) {
return &FileWatcher{
files: make(map[string]time.Time),
dirs: make(map[string]bool),
restartCh: make(chan bool, 1),
stopCh: make(chan bool, 1),
debounceMs: debounceMs,
@ -51,7 +52,16 @@ func (fw *FileWatcher) AddFile(path string) error {
}
func (fw *FileWatcher) AddDirectory(dir string) error {
return filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
absDir, err := filepath.Abs(dir)
if err != nil {
return err
}
fw.mu.Lock()
fw.dirs[absDir] = true
fw.mu.Unlock()
return filepath.Walk(absDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
@ -78,6 +88,7 @@ func (fw *FileWatcher) pollLoop() {
return
case <-ticker.C:
fw.checkFiles()
fw.scanForNewFiles()
}
}
}
@ -103,7 +114,7 @@ func (fw *FileWatcher) checkFiles() {
now := time.Now()
if now.Sub(fw.lastEvent) > time.Duration(fw.debounceMs)*time.Millisecond {
fw.lastEvent = now
log.Printf("File changed: %s", path)
// log.Printf("File changed: %s", path)
changed = true
}
}
@ -117,6 +128,57 @@ func (fw *FileWatcher) checkFiles() {
}
}
func (fw *FileWatcher) scanForNewFiles() {
fw.mu.RLock()
dirs := make(map[string]bool, len(fw.dirs))
maps.Copy(dirs, fw.dirs)
existingFiles := make(map[string]bool, len(fw.files))
for path := range fw.files {
existingFiles[path] = true
}
fw.mu.RUnlock()
newFilesFound := false
for dir := range dirs {
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() && strings.HasSuffix(path, ".lua") {
absPath, err := filepath.Abs(path)
if err != nil {
return err
}
if !existingFiles[absPath] {
fw.mu.Lock()
fw.files[absPath] = info.ModTime()
fw.mu.Unlock()
fmt.Printf("New file detected: %s\n", absPath)
newFilesFound = true
}
}
return nil
})
if err != nil {
continue
}
}
if newFilesFound {
now := time.Now()
if now.Sub(fw.lastEvent) > time.Duration(fw.debounceMs)*time.Millisecond {
fw.lastEvent = now
select {
case fw.restartCh <- true:
default:
}
}
}
}
func (fw *FileWatcher) Close() error {
select {
case fw.stopCh <- true: