diff --git a/moonshark-old.go b/moonshark-old.go deleted file mode 100644 index c958bc8..0000000 --- a/moonshark-old.go +++ /dev/null @@ -1,35 +0,0 @@ -package main - -/* -func (s *Moonshark) setupWatchers() { - manager := watchers.GetWatcherManager() - - // Watch routes - if routeWatcher, err := watchers.WatchLuaRouter(s.LuaRouter, s.LuaRunner, s.Config.Dirs.Routes); err != nil { - logger.Warnf("Routes directory watch failed: %v", err) - } else { - routesDir := routeWatcher.GetDir() - s.cleanupFuncs = append(s.cleanupFuncs, func() error { - return manager.UnwatchDirectory(routesDir) - }) - } - - // Watch modules - if moduleWatchers, err := watchers.WatchLuaModules(s.LuaRunner, s.Config.Dirs.Libs); err != nil { - logger.Warnf("Module directories watch failed: %v", err) - } else { - for _, watcher := range moduleWatchers { - dirPath := watcher.GetDir() - s.cleanupFuncs = append(s.cleanupFuncs, func() error { - return manager.UnwatchDirectory(dirPath) - }) - } - - plural := "directory" - if len(moduleWatchers) != 1 { - plural = "directories" - } - logger.Infof("Watching %s module %s.", color.Yellow(strconv.Itoa(len(moduleWatchers))), plural) - } -} -*/ diff --git a/moonshark.go b/moonshark.go index c8f8b13..5d513f4 100644 --- a/moonshark.go +++ b/moonshark.go @@ -9,6 +9,7 @@ import ( "Moonshark/runner" "Moonshark/sessions" "Moonshark/utils" + "Moonshark/watchers" "bytes" "context" "flag" @@ -17,6 +18,7 @@ import ( "os/signal" "path/filepath" "strconv" + "strings" "syscall" "time" @@ -33,6 +35,7 @@ var ( svr *fasthttp.Server // FastHTTP server pub fasthttp.RequestHandler // Public asset handler snm *sessions.SessionManager // Session data manager + wmg *watchers.WatcherManager // Watcher manager dbg bool // Debug mode flag pubPfx []byte // Cached public asset prefix ) @@ -83,6 +86,11 @@ func main() { logger.Fatalf("Router failed to init: %s", color.Red(err.Error())) } + // Set up the file watcher manager + if err := setupWatchers(); err != nil { + logger.Fatalf("Watcher manager failed to init: %s", color.Red(err.Error())) + } + // Set up the HTTP portion of the server logger.Http(cfg.Server.HTTPLogging) // Whether we'll log HTTP request results svr = http.NewHttpServer(cfg, requestMux, dbg) @@ -232,6 +240,46 @@ func initRouter() error { return nil } +// Set up the file watchers. +func setupWatchers() error { + wmg = watchers.NewWatcherManager(watchers.DefaultPollInterval) + + // Router watcher + err := wmg.WatchDirectory(watchers.DirectoryWatcherConfig{ + Dir: cfg.Dirs.Routes, + Callback: rtr.Refresh, + Recursive: true, + }) + if err != nil { + return fmt.Errorf("failed to watch routes directory: %v", err) + } + + logger.Infof("Started watching Lua routes! %s", color.Yellow(cfg.Dirs.Routes)) + + // Libs watchers + for _, dir := range cfg.Dirs.Libs { + err := wmg.WatchDirectory(watchers.DirectoryWatcherConfig{ + Dir: dir, + EnhancedCallback: func(changes []watchers.FileChange) error { + for _, change := range changes { + if !change.IsDeleted && strings.HasSuffix(change.Path, ".lua") { + rnr.NotifyFileChanged(change.Path) + } + } + return nil + }, + Recursive: true, + }) + if err != nil { + return fmt.Errorf("failed to watch modules directory: %v", err) + } + + logger.Infof("Started watching Lua modules! %s", color.Yellow(dir)) + } + + return nil +} + // Attempts to execute the Lua script at the given path inside a fully initialized sandbox environment. Handy // for pre-launch tasks and the like. func handleScriptMode(path string) error { @@ -263,6 +311,7 @@ func handleScriptMode(path string) error { func shutdown() { logger.Infof("Shutting down...") + // Close down the HTTP server if svr != nil { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() @@ -272,10 +321,16 @@ func shutdown() { } } + // Close down the Lua runner if it exists if rnr != nil { rnr.Close() } + // Close down the watcher manager if it exists + if wmg != nil { + wmg.Close() + } + logger.Infof("Shutdown complete") } diff --git a/runner/httpContext.go b/runner/httpContext.go index b7b1142..364cde3 100644 --- a/runner/httpContext.go +++ b/runner/httpContext.go @@ -7,6 +7,8 @@ import ( "Moonshark/utils" "sync" + "maps" + "github.com/valyala/fasthttp" ) @@ -69,9 +71,7 @@ func NewHTTPContext(httpCtx *fasthttp.RequestCtx, params *router.Params, session // Extract form data if present if httpCtx.IsPost() || httpCtx.IsPut() || httpCtx.IsPatch() { if form, err := utils.ParseForm(httpCtx); err == nil { - for k, v := range form { - ctx.form[k] = v - } + maps.Copy(ctx.form, form) } } @@ -88,9 +88,7 @@ func NewHTTPContext(httpCtx *fasthttp.RequestCtx, params *router.Params, session // Add environment vars if envMgr := lualibs.GetGlobalEnvManager(); envMgr != nil { - for k, v := range envMgr.GetAll() { - ctx.env[k] = v - } + maps.Copy(ctx.env, envMgr.GetAll()) } // Populate Values with all context data diff --git a/watchers/api.go b/watchers/api.go deleted file mode 100644 index c89c305..0000000 --- a/watchers/api.go +++ /dev/null @@ -1,85 +0,0 @@ -package watchers - -import ( - "fmt" - "strings" - "sync" - - "Moonshark/logger" - "Moonshark/router" - "Moonshark/runner" - - "git.sharkk.net/Go/Color" -) - -// Global watcher manager instance with explicit creation -var ( - globalManager *WatcherManager - globalManagerOnce sync.Once -) - -// GetWatcherManager returns the global watcher manager, creating it if needed -func GetWatcherManager() *WatcherManager { - globalManagerOnce.Do(func() { - globalManager = NewWatcherManager(DefaultPollInterval) - }) - return globalManager -} - -// ShutdownWatcherManager closes the global watcher manager if it exists -func ShutdownWatcherManager() { - if globalManager != nil { - globalManager.Close() - globalManager = nil - } -} - -// WatchLuaRouter sets up a watcher for a LuaRouter's routes directory -func WatchLuaRouter(router *router.Router, runner *runner.Runner, routesDir string) (*DirectoryWatcher, error) { - manager := GetWatcherManager() - - config := DirectoryWatcherConfig{ - Dir: routesDir, - Callback: router.Refresh, - Recursive: true, - } - - watcher, err := manager.WatchDirectory(config) - if err != nil { - return nil, fmt.Errorf("failed to watch directory: %w", err) - } - - logger.Infof("Started watching Lua routes! %s", color.Yellow(routesDir)) - return watcher, nil -} - -// WatchLuaModules sets up watchers for Lua module directories -func WatchLuaModules(luaRunner *runner.Runner, libDirs []string) ([]*DirectoryWatcher, error) { - manager := GetWatcherManager() - watchers := make([]*DirectoryWatcher, 0, len(libDirs)) - - for _, dir := range libDirs { - config := DirectoryWatcherConfig{ - Dir: dir, - EnhancedCallback: func(changes []FileChange) error { - for _, change := range changes { - if !change.IsDeleted && strings.HasSuffix(change.Path, ".lua") { - luaRunner.NotifyFileChanged(change.Path) - } - } - return nil - }, - Recursive: true, - } - - watcher, err := manager.WatchDirectory(config) - if err != nil { - // Error handling... - } - - watchers = append(watchers, watcher) - logger.Infof("Started watching Lua modules! %s", color.Yellow(dir)) - } - - return watchers, nil -} diff --git a/watchers/manager.go b/watchers/manager.go index 6b3fa91..cfff110 100644 --- a/watchers/manager.go +++ b/watchers/manager.go @@ -11,7 +11,6 @@ import ( // DefaultPollInterval is the time between directory checks const DefaultPollInterval = 1 * time.Second -// Common errors var ( ErrDirectoryNotFound = errors.New("directory not found") ErrAlreadyWatching = errors.New("already watching directory") @@ -59,12 +58,12 @@ func (m *WatcherManager) Close() error { } // WatchDirectory adds a new directory to watch and returns the watcher -func (m *WatcherManager) WatchDirectory(config DirectoryWatcherConfig) (*DirectoryWatcher, error) { +func (m *WatcherManager) WatchDirectory(config DirectoryWatcherConfig) error { m.mu.Lock() defer m.mu.Unlock() if _, exists := m.watchers[config.Dir]; exists { - return nil, ErrAlreadyWatching + return ErrAlreadyWatching } if config.DebounceTime == 0 { @@ -82,13 +81,13 @@ func (m *WatcherManager) WatchDirectory(config DirectoryWatcherConfig) (*Directo // Perform initial scan if err := watcher.scanDirectory(); err != nil { - return nil, err + return err } m.watchers[config.Dir] = watcher logger.Debugf("WatcherManager added watcher for %s", config.Dir) - return watcher, nil + return nil } // UnwatchDirectory removes a directory from being watched