Moonshark/core/runner/CoreModules.go
2025-04-08 22:10:50 -05:00

263 lines
6.9 KiB
Go

package runner
import (
"Moonshark/core/runner/sandbox"
"Moonshark/core/utils/logger"
"fmt"
"strings"
"sync"
luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
)
// CoreModuleRegistry manages the initialization and reloading of core modules
type CoreModuleRegistry struct {
modules map[string]sandbox.StateInitFunc // Module initializers
initOrder []string // Explicit initialization order
dependencies map[string][]string // Module dependencies
initializedFlag map[string]bool // Track which modules are initialized
mu sync.RWMutex
debug bool
}
// NewCoreModuleRegistry creates a new core module registry
func NewCoreModuleRegistry() *CoreModuleRegistry {
return &CoreModuleRegistry{
modules: make(map[string]sandbox.StateInitFunc),
initOrder: []string{},
dependencies: make(map[string][]string),
initializedFlag: make(map[string]bool),
debug: false,
}
}
// EnableDebug turns on debug logging
func (r *CoreModuleRegistry) EnableDebug() {
r.debug = true
}
// debugLog prints debug messages if enabled
func (r *CoreModuleRegistry) debugLog(format string, args ...interface{}) {
if r.debug {
logger.Debug("CoreRegistry "+format, args...)
}
}
// Register adds a module to the registry
func (r *CoreModuleRegistry) Register(name string, initFunc sandbox.StateInitFunc) {
r.mu.Lock()
defer r.mu.Unlock()
r.modules[name] = initFunc
// Add to initialization order if not already there
for _, n := range r.initOrder {
if n == name {
return // Already registered
}
}
r.initOrder = append(r.initOrder, name)
r.debugLog("registered module %s", name)
}
// RegisterWithDependencies registers a module with explicit dependencies
func (r *CoreModuleRegistry) RegisterWithDependencies(name string, initFunc sandbox.StateInitFunc, dependencies []string) {
r.mu.Lock()
defer r.mu.Unlock()
r.modules[name] = initFunc
r.dependencies[name] = dependencies
// Add to initialization order if not already there
for _, n := range r.initOrder {
if n == name {
return // Already registered
}
}
r.initOrder = append(r.initOrder, name)
r.debugLog("registered module %s with dependencies: %v", name, dependencies)
}
// SetInitOrder sets explicit initialization order
func (r *CoreModuleRegistry) SetInitOrder(order []string) {
r.mu.Lock()
defer r.mu.Unlock()
// Create new init order
newOrder := make([]string, 0, len(order))
// First add all known modules that are in the specified order
for _, name := range order {
if _, exists := r.modules[name]; exists && !contains(newOrder, name) {
newOrder = append(newOrder, name)
}
}
// Then add any modules not in the specified order
for name := range r.modules {
if !contains(newOrder, name) {
newOrder = append(newOrder, name)
}
}
r.initOrder = newOrder
r.debugLog("Set initialization order: %v", r.initOrder)
}
// Initialize initializes all registered modules
func (r *CoreModuleRegistry) Initialize(state *luajit.State, stateIndex int) error {
r.mu.RLock()
defer r.mu.RUnlock()
verbose := stateIndex == 0
if verbose {
r.debugLog("initializing %d modules...", len(r.initOrder))
}
// Clear initialization flags
r.initializedFlag = make(map[string]bool)
// Initialize modules in order, respecting dependencies
for _, name := range r.initOrder {
if err := r.initializeModule(state, name, []string{}, verbose); err != nil {
return err
}
}
if verbose {
r.debugLog("All modules initialized successfully")
}
return nil
}
// initializeModule initializes a module and its dependencies
func (r *CoreModuleRegistry) initializeModule(state *luajit.State, name string,
initStack []string, verbose bool) error {
// Check if already initialized
if r.initializedFlag[name] {
return nil
}
// Check for circular dependencies
for _, n := range initStack {
if n == name {
return fmt.Errorf("circular dependency detected: %s -> %s",
strings.Join(initStack, " -> "), name)
}
}
// Get init function
initFunc, ok := r.modules[name]
if !ok {
return fmt.Errorf("module not found: %s", name)
}
// Initialize dependencies first
deps := r.dependencies[name]
if len(deps) > 0 {
newStack := append(initStack, name)
for _, dep := range deps {
if err := r.initializeModule(state, dep, newStack, verbose); err != nil {
return err
}
}
}
err := initFunc(state)
if err != nil {
// Always log failures regardless of verbose setting
r.debugLog("Initializing module %s... failure: %v", name, err)
return fmt.Errorf("failed to initialize module %s: %w", name, err)
}
r.initializedFlag[name] = true
if verbose {
r.debugLog("Initializing module %s... success", name)
}
return nil
}
// InitializeModule initializes a specific module
func (r *CoreModuleRegistry) InitializeModule(state *luajit.State, name string) error {
r.mu.RLock()
defer r.mu.RUnlock()
// Clear initialization flag for this module
r.initializedFlag[name] = false
// Always use verbose logging for explicit module initialization
return r.initializeModule(state, name, []string{}, true)
}
// MatchModuleName checks if a file path corresponds to a registered module
func (r *CoreModuleRegistry) MatchModuleName(modName string) (string, bool) {
r.mu.RLock()
defer r.mu.RUnlock()
// Exact match
if _, ok := r.modules[modName]; ok {
return modName, true
}
// Check if the module name ends with a registered module
for name := range r.modules {
if strings.HasSuffix(modName, "."+name) {
return name, true
}
}
return "", false
}
// Global registry instance
var GlobalRegistry = NewCoreModuleRegistry()
// Initialize global registry with core modules
func init() {
GlobalRegistry.EnableDebug() // Enable debugging by default
logger.Debug("[ModuleRegistry] Registering core modules...")
// Register core modules
GlobalRegistry.Register("util", func(state *luajit.State) error {
return sandbox.UtilModuleInitFunc()(state)
})
GlobalRegistry.Register("http", func(state *luajit.State) error {
return sandbox.HTTPModuleInitFunc()(state)
})
// Set explicit initialization order
GlobalRegistry.SetInitOrder([]string{
"util", // First: core utilities
"http", // Second: HTTP functionality
"session", // Third: Session functionality
"csrf", // Fourth: CSRF protection
})
logger.Debug("Core modules registered successfully")
}
// RegisterCoreModule registers a core module with the global registry
func RegisterCoreModule(name string, initFunc sandbox.StateInitFunc) {
GlobalRegistry.Register(name, initFunc)
}
// RegisterCoreModuleWithDependencies registers a module with dependencies
func RegisterCoreModuleWithDependencies(name string, initFunc sandbox.StateInitFunc, dependencies []string) {
GlobalRegistry.RegisterWithDependencies(name, initFunc, dependencies)
}
// Helper functions
func contains(slice []string, item string) bool {
for _, s := range slice {
if s == item {
return true
}
}
return false
}