250 lines
6.9 KiB
Go
250 lines
6.9 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
"time"
|
|
|
|
"git.sharkk.net/Sky/Moonshark/core/config"
|
|
"git.sharkk.net/Sky/Moonshark/core/http"
|
|
"git.sharkk.net/Sky/Moonshark/core/logger"
|
|
"git.sharkk.net/Sky/Moonshark/core/routers"
|
|
"git.sharkk.net/Sky/Moonshark/core/runner"
|
|
"git.sharkk.net/Sky/Moonshark/core/utils"
|
|
"git.sharkk.net/Sky/Moonshark/core/watchers"
|
|
)
|
|
|
|
// WatcherConfig holds the configuration for which watchers to enable
|
|
type WatcherConfig struct {
|
|
Routes bool
|
|
Static bool
|
|
Modules bool
|
|
}
|
|
|
|
// initRouters sets up the Lua and static routers
|
|
func initRouters(routesDir, staticDir string, log *logger.Logger) (*routers.LuaRouter, *routers.StaticRouter, error) {
|
|
// Ensure directories exist
|
|
if err := utils.EnsureDir(routesDir); err != nil {
|
|
return nil, nil, fmt.Errorf("routes directory doesn't exist, and could not create it: %v", err)
|
|
}
|
|
if err := utils.EnsureDir(staticDir); err != nil {
|
|
return nil, nil, fmt.Errorf("static directory doesn't exist, and could not create it: %v", err)
|
|
}
|
|
|
|
// Initialize Lua router for dynamic routes
|
|
luaRouter, err := routers.NewLuaRouter(routesDir)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to initialize Lua router: %v", err)
|
|
}
|
|
log.Info("Lua router initialized with routes from %s", routesDir)
|
|
|
|
// Initialize static file router
|
|
staticRouter, err := routers.NewStaticRouterWithLogger(staticDir, log)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to initialize static router: %v", err)
|
|
}
|
|
log.Info("Static router initialized with files from %s", staticDir)
|
|
staticRouter.EnableDebugLog()
|
|
|
|
return luaRouter, staticRouter, nil
|
|
}
|
|
|
|
// setupWatchers initializes and starts all file watchers
|
|
func setupWatchers(luaRouter *routers.LuaRouter, staticRouter *routers.StaticRouter,
|
|
luaRunner *runner.LuaRunner, routesDir string, staticDir string,
|
|
libDirs []string, log *logger.Logger, config WatcherConfig) ([]func() error, error) {
|
|
|
|
var cleanupFuncs []func() error
|
|
|
|
// Set up watcher for Lua routes
|
|
if config.Routes {
|
|
luaRouterWatcher, err := watchers.WatchLuaRouter(luaRouter, routesDir, log)
|
|
if err != nil {
|
|
log.Warning("Failed to watch routes directory: %v", err)
|
|
} else {
|
|
cleanupFuncs = append(cleanupFuncs, luaRouterWatcher.Close)
|
|
log.Info("File watcher active for Lua routes")
|
|
}
|
|
}
|
|
|
|
// Set up watcher for static files
|
|
if config.Static {
|
|
staticWatcher, err := watchers.WatchStaticRouter(staticRouter, staticDir, log)
|
|
if err != nil {
|
|
log.Warning("Failed to watch static directory: %v", err)
|
|
} else {
|
|
cleanupFuncs = append(cleanupFuncs, staticWatcher.Close)
|
|
log.Info("File watcher active for static files")
|
|
}
|
|
}
|
|
|
|
// Set up watchers for Lua modules libraries
|
|
if config.Modules && len(libDirs) > 0 {
|
|
moduleWatchers, err := watchers.WatchLuaModules(luaRunner, libDirs, log)
|
|
if err != nil {
|
|
log.Warning("Failed to watch Lua module directories: %v", err)
|
|
} else {
|
|
for _, watcher := range moduleWatchers {
|
|
w := watcher // Capture variable for closure
|
|
cleanupFuncs = append(cleanupFuncs, w.Close)
|
|
}
|
|
log.Info("File watchers active for %d Lua module directories", len(moduleWatchers))
|
|
}
|
|
}
|
|
|
|
return cleanupFuncs, nil
|
|
}
|
|
|
|
func main() {
|
|
// Initialize logger
|
|
log := logger.New(logger.LevelDebug, true)
|
|
|
|
log.Server("Starting Moonshark server")
|
|
|
|
// Load configuration from config.lua
|
|
cfg, err := config.Load("config.lua")
|
|
if err != nil {
|
|
log.Warning("Failed to load config.lua: %v", err)
|
|
log.Info("Using default configuration")
|
|
cfg = config.New()
|
|
}
|
|
|
|
// Set log level from config
|
|
switch cfg.GetString("log_level", "info") {
|
|
case "debug":
|
|
log.SetLevel(logger.LevelDebug)
|
|
case "warn":
|
|
log.SetLevel(logger.LevelWarning)
|
|
case "error":
|
|
log.SetLevel(logger.LevelError)
|
|
case "server":
|
|
log.SetLevel(logger.LevelServer)
|
|
case "fatal":
|
|
log.SetLevel(logger.LevelFatal)
|
|
default:
|
|
log.SetLevel(logger.LevelInfo)
|
|
}
|
|
|
|
// Get configuration values
|
|
port := cfg.GetInt("port", 3117)
|
|
routesDir := cfg.GetString("routes_dir", "./routes")
|
|
staticDir := cfg.GetString("static_dir", "./static")
|
|
bufferSize := cfg.GetInt("buffer_size", 20)
|
|
|
|
// Get library directories
|
|
var libDirs []string
|
|
libDirsConfig := cfg.GetStringArray("lib_dirs")
|
|
if libDirsConfig != nil && len(libDirsConfig) > 0 {
|
|
libDirs = libDirsConfig
|
|
} else {
|
|
// Default lib directory
|
|
libDirs = []string{"./libs"}
|
|
}
|
|
|
|
// Ensure lib directories exist
|
|
for _, dir := range libDirs {
|
|
if err := utils.EnsureDir(dir); err != nil {
|
|
log.Warning("Lib directory doesn't exist, and could not create it: %v", err)
|
|
}
|
|
}
|
|
|
|
// Initialize routers
|
|
luaRouter, staticRouter, err := initRouters(routesDir, staticDir, log)
|
|
if err != nil {
|
|
log.Fatal("Router initialization failed: %v", err)
|
|
}
|
|
|
|
// Initialize Lua runner
|
|
luaRunner, err := runner.NewRunner(
|
|
runner.WithBufferSize(bufferSize),
|
|
runner.WithLibDirs(libDirs...),
|
|
)
|
|
if err != nil {
|
|
log.Fatal("Failed to initialize Lua runner: %v", err)
|
|
}
|
|
log.Server("Lua runner initialized with buffer size %d", bufferSize)
|
|
defer luaRunner.Close()
|
|
|
|
// Set up file watchers if enabled
|
|
var cleanupFuncs []func() error
|
|
|
|
// Get watcher configuration (default all disabled)
|
|
watcherConfig := WatcherConfig{
|
|
Routes: false,
|
|
Static: false,
|
|
Modules: false,
|
|
}
|
|
|
|
// Enable watchers based on map configuration
|
|
watchersMap := cfg.GetMap("watchers")
|
|
if watchersMap != nil {
|
|
if routes, ok := watchersMap["routes"].(bool); ok && routes {
|
|
watcherConfig.Routes = true
|
|
}
|
|
if static, ok := watchersMap["static"].(bool); ok && static {
|
|
watcherConfig.Static = true
|
|
}
|
|
if modules, ok := watchersMap["modules"].(bool); ok && modules {
|
|
watcherConfig.Modules = true
|
|
}
|
|
}
|
|
|
|
// Setup enabled watchers
|
|
cleanupFuncs, err = setupWatchers(luaRouter, staticRouter, luaRunner,
|
|
routesDir, staticDir, libDirs, log, watcherConfig)
|
|
if err != nil {
|
|
log.Warning("Error setting up watchers: %v", err)
|
|
}
|
|
|
|
// Register cleanup functions
|
|
defer func() {
|
|
for _, cleanup := range cleanupFuncs {
|
|
if err := cleanup(); err != nil {
|
|
log.Warning("Cleanup error: %v", err)
|
|
}
|
|
}
|
|
}()
|
|
|
|
httpLoggingEnabled := cfg.GetBool("http_logging_enabled", true)
|
|
if httpLoggingEnabled {
|
|
log.Info("HTTP logging is enabled")
|
|
} else {
|
|
log.Info("HTTP logging is disabled")
|
|
}
|
|
|
|
// Create HTTP server
|
|
server := http.New(luaRouter, staticRouter, luaRunner, log, httpLoggingEnabled)
|
|
|
|
// Handle graceful shutdown
|
|
stop := make(chan os.Signal, 1)
|
|
signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
|
|
|
|
// Start server in a goroutine
|
|
go func() {
|
|
if err := server.ListenAndServe(fmt.Sprintf(":%d", port)); err != nil {
|
|
if err.Error() != "http: Server closed" {
|
|
log.Error("Server error: %v", err)
|
|
}
|
|
}
|
|
}()
|
|
|
|
log.Server("Server started on port %d", port)
|
|
|
|
// Wait for interrupt signal
|
|
<-stop
|
|
log.Server("Shutdown signal received")
|
|
|
|
// Gracefully shut down the server
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer cancel()
|
|
|
|
if err := server.Shutdown(ctx); err != nil {
|
|
log.Error("Server shutdown error: %v", err)
|
|
}
|
|
|
|
log.Server("Server stopped")
|
|
}
|