Moonshark/moonshark.go

169 lines
3.6 KiB
Go

package main
import (
"flag"
"fmt"
"log"
"os"
"os/signal"
"path/filepath"
"syscall"
"time"
"Moonshark/modules/http"
"Moonshark/modules/sql"
"Moonshark/state"
)
var (
watchFlag = flag.Bool("watch", false, "Watch script files for changes and restart")
wFlag = flag.Bool("w", false, "Watch script files for changes and restart")
)
func main() {
flag.Parse()
if flag.NArg() < 1 {
fmt.Fprintf(os.Stderr, "Usage: %s [--watch|-w] <script.lua>\n", filepath.Base(os.Args[0]))
os.Exit(1)
}
scriptPath := flag.Arg(0)
watchMode := *watchFlag || *wFlag
if watchMode {
runWithWatcher(scriptPath)
} else {
runOnce(scriptPath)
}
}
func runOnce(scriptPath string) {
luaState, err := state.NewFromScript(scriptPath)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
defer luaState.Close()
if err := luaState.ExecuteFile(scriptPath); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
if http.HasActiveServers() {
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
fmt.Println("HTTP servers running. Press Ctrl+C to exit.")
go func() {
<-sigChan
fmt.Println("\nShutting down...")
// Close main state first (saves KV stores)
luaState.Close()
// Then stop servers (closes worker states)
http.StopAllServers()
sql.CloseAllConnections()
os.Exit(0)
}()
http.WaitForServers()
}
}
func runWithWatcher(scriptPath string) {
watcher, err := NewFileWatcher(500) // 500ms debounce
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to create file watcher: %v\n", err)
os.Exit(1)
}
defer watcher.Close()
if err := watcher.DiscoverRequiredFiles(scriptPath); err != nil {
fmt.Fprintf(os.Stderr, "Failed to watch files: %v\n", err)
os.Exit(1)
}
restartCh := watcher.Start()
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
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()
// Create and run state
luaState, err := state.NewFromScript(scriptPath)
if err != nil {
log.Printf("Error creating state: %v", err)
hadError = true
continue
}
if err := luaState.ExecuteFile(scriptPath); err != nil {
log.Printf("Execution error: %v", err)
luaState.Close()
hadError = true
continue
}
// If not a long-running process, wait for changes and restart
if !http.HasActiveServers() {
fmt.Println("Script completed. Waiting for changes...")
luaState.Close()
select {
case <-restartCh:
fmt.Println("Files changed, restarting...")
continue
case <-sigChan:
fmt.Println("\nExiting...")
return
}
}
// Long-running process - wait for restart signal or exit signal
fmt.Println("HTTP servers running. Watching for file changes...")
select {
case <-restartCh:
fmt.Println("Files changed, restarting...")
http.StopAllServers()
luaState.Close()
sql.CloseAllConnections()
time.Sleep(100 * time.Millisecond) // Brief pause for cleanup
continue
case <-sigChan:
fmt.Println("\nShutting down...")
http.StopAllServers()
luaState.Close()
sql.CloseAllConnections()
return
}
}
}