Moonshark/core/watchers/Api.go

146 lines
3.5 KiB
Go

package watchers
import (
"fmt"
"sync"
"Moonshark/core/routers"
"Moonshark/core/runner"
"Moonshark/core/utils/logger"
)
// Global watcher manager instance
var (
globalManager *WatcherManager
globalManagerOnce sync.Once
)
// GetWatcherManager returns the global watcher manager, creating it if needed
func GetWatcherManager(adaptive bool) *WatcherManager {
globalManagerOnce.Do(func() {
globalManager = NewWatcherManager()
})
return globalManager
}
// WatchDirectory creates a new directory watcher and registers it with the manager
func WatchDirectory(config DirectoryWatcherConfig, manager *WatcherManager) (*Watcher, error) {
dirWatcher, err := NewDirectoryWatcher(config)
if err != nil {
return nil, fmt.Errorf("failed to create directory watcher: %w", err)
}
manager.AddWatcher(dirWatcher)
// Create a wrapper Watcher that implements the old interface
w := &Watcher{
dir: config.Dir,
dirWatch: dirWatcher,
manager: manager,
}
return w, nil
}
// Watcher is a compatibility wrapper that maintains the old API
type Watcher struct {
dir string
dirWatch *DirectoryWatcher
manager *WatcherManager
}
// Close unregisters the watcher from the manager
func (w *Watcher) Close() error {
w.manager.RemoveWatcher(w.dir)
return nil
}
// WatchLuaRouter sets up a watcher for a LuaRouter's routes directory; also updates
// the LuaRunner so that the state can be rebuilt
func WatchLuaRouter(router *routers.LuaRouter, runner *runner.Runner, routesDir string) (*Watcher, error) {
manager := GetWatcherManager(true)
runnerRefresh := func() error {
logger.Debug("Refreshing LuaRunner state due to file change")
runner.NotifyFileChanged("")
return nil
}
combinedCallback := combineCallbacks(router.Refresh, runnerRefresh)
config := DirectoryWatcherConfig{
Dir: routesDir,
Callback: combinedCallback,
Recursive: true,
}
watcher, err := WatchDirectory(config, manager)
if err != nil {
return nil, err
}
logger.Info("Started watching Lua routes directory: %s", routesDir)
return watcher, nil
}
// WatchLuaModules sets up watchers for Lua module directories
func WatchLuaModules(luaRunner *runner.Runner, libDirs []string) ([]*Watcher, error) {
manager := GetWatcherManager(true)
watchers := make([]*Watcher, 0, len(libDirs))
for _, dir := range libDirs {
// Create a directory-specific callback
dirCopy := dir // Capture for closure
callback := func() error {
logger.Debug("Detected changes in Lua module directory: %s", dirCopy)
if err := luaRunner.RefreshStates(); err != nil {
logger.Warning("Error reloading modules: %v", err)
}
return nil
}
config := DirectoryWatcherConfig{
Dir: dir,
Callback: callback,
Recursive: true,
}
watcher, err := WatchDirectory(config, manager)
if err != nil {
// Clean up already created watchers
for _, w := range watchers {
w.Close()
}
return nil, err
}
watchers = append(watchers, watcher)
logger.Info("Started watching Lua modules directory: %s", dir)
}
return watchers, nil
}
// ShutdownWatcherManager closes the global watcher manager if it exists
func ShutdownWatcherManager() {
if globalManager != nil {
globalManager.Close()
globalManager = nil
}
}
// combineCallbacks creates a single callback function from multiple callbacks
func combineCallbacks(callbacks ...func() error) func() error {
return func() error {
for _, callback := range callbacks {
if err := callback(); err != nil {
return err
}
}
return nil
}
}