reorg 1, watcher op 1

This commit is contained in:
Sky Johnson 2025-04-05 22:09:06 -05:00
parent 3a10b22bac
commit ed770f069c
22 changed files with 89 additions and 148 deletions

View File

@ -6,13 +6,13 @@ import (
"fmt" "fmt"
"time" "time"
"Moonshark/core/config"
"Moonshark/core/http" "Moonshark/core/http"
"Moonshark/core/logger"
"Moonshark/core/routers" "Moonshark/core/routers"
"Moonshark/core/runner" "Moonshark/core/runner"
"Moonshark/core/sessions" "Moonshark/core/sessions"
"Moonshark/core/utils" "Moonshark/core/utils"
"Moonshark/core/utils/config"
"Moonshark/core/utils/logger"
"Moonshark/core/watchers" "Moonshark/core/watchers"
) )

View File

@ -1,8 +1,8 @@
package http package http
import ( import (
"Moonshark/core/logger"
"Moonshark/core/utils" "Moonshark/core/utils"
"Moonshark/core/utils/logger"
"github.com/valyala/fasthttp" "github.com/valyala/fasthttp"
) )

View File

@ -3,7 +3,7 @@ package http
import ( import (
"time" "time"
"Moonshark/core/logger" "Moonshark/core/utils/logger"
) )
// StatusColors for different status code ranges // StatusColors for different status code ranges

View File

@ -6,12 +6,12 @@ import (
"fmt" "fmt"
"time" "time"
"Moonshark/core/config"
"Moonshark/core/logger"
"Moonshark/core/metadata" "Moonshark/core/metadata"
"Moonshark/core/routers" "Moonshark/core/routers"
"Moonshark/core/runner" "Moonshark/core/runner"
"Moonshark/core/utils" "Moonshark/core/utils"
"Moonshark/core/utils/config"
"Moonshark/core/utils/logger"
"github.com/valyala/fasthttp" "github.com/valyala/fasthttp"
) )

View File

@ -8,7 +8,7 @@ import (
"strings" "strings"
"time" "time"
"Moonshark/core/logger" "Moonshark/core/utils/logger"
"github.com/valyala/fasthttp" "github.com/valyala/fasthttp"
) )

View File

@ -1,12 +1,11 @@
package runner package runner
import ( import (
"Moonshark/core/utils/logger"
"fmt" "fmt"
"strings" "strings"
"sync" "sync"
"Moonshark/core/logger"
luajit "git.sharkk.net/Sky/LuaJIT-to-Go" luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
) )
@ -269,11 +268,11 @@ func init() {
GlobalRegistry.Register("util", UtilModuleInitFunc()) GlobalRegistry.Register("util", UtilModuleInitFunc())
GlobalRegistry.Register("http", HTTPModuleInitFunc()) GlobalRegistry.Register("http", HTTPModuleInitFunc())
GlobalRegistry.RegisterWithDependencies("cookie", CookieModuleInitFunc(), []string{"http"}) GlobalRegistry.RegisterWithDependencies("cookie", CookieModuleInitFunc(), []string{"http"})
GlobalRegistry.RegisterWithDependencies("csrf", CSRFModuleInitFunc(), []string{"go"}) GlobalRegistry.RegisterWithDependencies("csrf", CSRFModuleInitFunc(), []string{"util"})
// Set explicit initialization order // Set explicit initialization order
GlobalRegistry.SetInitOrder([]string{ GlobalRegistry.SetInitOrder([]string{
"go", // First: core utilities "util", // First: core utilities
"http", // Second: HTTP functionality "http", // Second: HTTP functionality
"cookie", // Third: Cookie functionality (uses HTTP) "cookie", // Third: Cookie functionality (uses HTTP)
"csrf", // Fourth: CSRF protection (uses go and possibly session) "csrf", // Fourth: CSRF protection (uses go and possibly session)

View File

@ -3,7 +3,7 @@ package runner
import ( import (
"crypto/subtle" "crypto/subtle"
"Moonshark/core/logger" "Moonshark/core/utils/logger"
luajit "git.sharkk.net/Sky/LuaJIT-to-Go" luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
) )

View File

@ -1,7 +1,7 @@
package runner package runner
import ( import (
"Moonshark/core/logger" "Moonshark/core/utils/logger"
luajit "git.sharkk.net/Sky/LuaJIT-to-Go" luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
) )

View File

@ -14,7 +14,7 @@ import (
"github.com/valyala/bytebufferpool" "github.com/valyala/bytebufferpool"
"github.com/valyala/fasthttp" "github.com/valyala/fasthttp"
"Moonshark/core/logger" "Moonshark/core/utils/logger"
luajit "git.sharkk.net/Sky/LuaJIT-to-Go" luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
) )

View File

@ -12,7 +12,7 @@ import (
"github.com/panjf2000/ants/v2" "github.com/panjf2000/ants/v2"
"github.com/valyala/bytebufferpool" "github.com/valyala/bytebufferpool"
"Moonshark/core/logger" "Moonshark/core/utils/logger"
luajit "git.sharkk.net/Sky/LuaJIT-to-Go" luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
) )

View File

@ -7,7 +7,7 @@ import (
"github.com/goccy/go-json" "github.com/goccy/go-json"
"github.com/valyala/bytebufferpool" "github.com/valyala/bytebufferpool"
"Moonshark/core/logger" "Moonshark/core/utils/logger"
luajit "git.sharkk.net/Sky/LuaJIT-to-Go" luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
) )

View File

@ -3,8 +3,8 @@ package runner
import ( import (
"net/http" "net/http"
"Moonshark/core/logger"
"Moonshark/core/sessions" "Moonshark/core/sessions"
"Moonshark/core/utils/logger"
luajit "git.sharkk.net/Sky/LuaJIT-to-Go" luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
) )

View File

@ -1,7 +1,7 @@
package runner package runner
import ( import (
"Moonshark/core/logger" "Moonshark/core/utils/logger"
luajit "git.sharkk.net/Sky/LuaJIT-to-Go" luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
) )

View File

@ -4,7 +4,7 @@ import (
"crypto/rand" "crypto/rand"
"encoding/base64" "encoding/base64"
"Moonshark/core/logger" "Moonshark/core/utils/logger"
luajit "git.sharkk.net/Sky/LuaJIT-to-Go" luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
) )

View File

@ -7,8 +7,8 @@ import (
"strings" "strings"
"time" "time"
"Moonshark/core/config"
"Moonshark/core/metadata" "Moonshark/core/metadata"
"Moonshark/core/utils/config"
) )
// ComponentStats holds stats from various system components // ComponentStats holds stats from various system components
@ -26,7 +26,7 @@ type SystemStats struct {
Memory runtime.MemStats Memory runtime.MemStats
Components ComponentStats Components ComponentStats
Version string Version string
Config *config.Config // Configuration information Config *config.Config
} }
// CollectSystemStats gathers basic system statistics // CollectSystemStats gathers basic system statistics

View File

@ -8,25 +8,20 @@ import (
// EnsureDir checks if a directory exists and creates it if it doesn't. // EnsureDir checks if a directory exists and creates it if it doesn't.
// Returns any error encountered during directory creation. // Returns any error encountered during directory creation.
func EnsureDir(path string) error { func EnsureDir(path string) error {
// Clean the path to handle any malformed input
path = filepath.Clean(path) path = filepath.Clean(path)
// Check if the directory exists
info, err := os.Stat(path) info, err := os.Stat(path)
// If no error, check if it's a directory
if err == nil { if err == nil {
if info.IsDir() { if info.IsDir() {
return nil // Directory already exists return nil
} }
return os.ErrExist // Path exists but is not a directory return os.ErrExist
} }
// If the error is not that the path doesn't exist, return it
if !os.IsNotExist(err) { if !os.IsNotExist(err) {
return err return err
} }
// Create the directory with default permissions (0755)
return os.MkdirAll(path, 0755) return os.MkdirAll(path, 0755)
} }

View File

@ -39,7 +39,7 @@ type Config struct {
values map[string]any values map[string]any
} }
// New creates a new configuration with default values // NewConfig creates a new configuration with default values
func New() *Config { func New() *Config {
config := &Config{ config := &Config{
// Initialize values map // Initialize values map

View File

@ -4,9 +4,9 @@ import (
"fmt" "fmt"
"sync" "sync"
"Moonshark/core/logger"
"Moonshark/core/routers" "Moonshark/core/routers"
"Moonshark/core/runner" "Moonshark/core/runner"
"Moonshark/core/utils/logger"
) )
// Global watcher manager instance // Global watcher manager instance
@ -18,7 +18,7 @@ var (
// GetWatcherManager returns the global watcher manager, creating it if needed // GetWatcherManager returns the global watcher manager, creating it if needed
func GetWatcherManager(adaptive bool) *WatcherManager { func GetWatcherManager(adaptive bool) *WatcherManager {
globalManagerOnce.Do(func() { globalManagerOnce.Do(func() {
globalManager = NewWatcherManager(adaptive) globalManager = NewWatcherManager()
}) })
return globalManager return globalManager
} }

View File

@ -7,7 +7,7 @@ import (
"sync" "sync"
"time" "time"
"Moonshark/core/logger" "Moonshark/core/utils/logger"
) )
// Default debounce time between detected change and callback // Default debounce time between detected change and callback
@ -42,17 +42,10 @@ type DirectoryWatcher struct {
// DirectoryWatcherConfig contains configuration for a directory watcher // DirectoryWatcherConfig contains configuration for a directory watcher
type DirectoryWatcherConfig struct { type DirectoryWatcherConfig struct {
// Directory to watch Dir string // Directory to watch
Dir string Callback func() error // Callback function to call when changes are detected
DebounceTime time.Duration // Debounce time (0 means use default)
// Callback function to call when changes are detected Recursive bool // Recursive watching (watch subdirectories)
Callback func() error
// Debounce time (0 means use default)
DebounceTime time.Duration
// Recursive watching (watch subdirectories)
Recursive bool
} }
// NewDirectoryWatcher creates a new directory watcher // NewDirectoryWatcher creates a new directory watcher
@ -83,13 +76,15 @@ func (w *DirectoryWatcher) scanDirectory() error {
w.filesMu.Lock() w.filesMu.Lock()
defer w.filesMu.Unlock() defer w.filesMu.Unlock()
// Clear existing files map
w.files = make(map[string]FileInfo)
return filepath.Walk(w.dir, func(path string, info os.FileInfo, err error) error { return filepath.Walk(w.dir, func(path string, info os.FileInfo, err error) error {
if err != nil { if err != nil {
w.logWarning("Error accessing path %s: %v", path, err) return nil // Skip files with errors
return nil // Continue with other files
} }
// Skip if not recursive and this is a subdirectory // Skip subdirectories if not recursive
if !w.recursive && info.IsDir() && path != w.dir { if !w.recursive && info.IsDir() && path != w.dir {
return filepath.SkipDir return filepath.SkipDir
} }
@ -106,25 +101,46 @@ func (w *DirectoryWatcher) scanDirectory() error {
// checkForChanges detects if any files have been added, modified, or deleted // checkForChanges detects if any files have been added, modified, or deleted
func (w *DirectoryWatcher) checkForChanges() (bool, error) { func (w *DirectoryWatcher) checkForChanges() (bool, error) {
// Get current state // Lock for reading previous state
currentFiles := make(map[string]FileInfo) w.filesMu.RLock()
prevFileCount := len(w.files)
w.filesMu.RUnlock()
// Track new state and whether changes were detected
newFiles := make(map[string]FileInfo)
changed := false
// Walk the directory to check for changes
err := filepath.Walk(w.dir, func(path string, info os.FileInfo, err error) error { err := filepath.Walk(w.dir, func(path string, info os.FileInfo, err error) error {
// Skip errors (file might have been deleted)
if err != nil { if err != nil {
// File might have been deleted between directory read and stat
return nil return nil
} }
// Skip if not recursive and this is a subdirectory // Skip subdirectories if not recursive
if !w.recursive && info.IsDir() && path != w.dir { if !w.recursive && info.IsDir() && path != w.dir {
return filepath.SkipDir return filepath.SkipDir
} }
currentFiles[path] = FileInfo{ // Store current file info
currentInfo := FileInfo{
ModTime: info.ModTime(), ModTime: info.ModTime(),
Size: info.Size(), Size: info.Size(),
IsDir: info.IsDir(), IsDir: info.IsDir(),
} }
newFiles[path] = currentInfo
// Check if file is new or modified (only if we haven't already detected a change)
if !changed {
w.filesMu.RLock()
prevInfo, exists := w.files[path]
w.filesMu.RUnlock()
if !exists || currentInfo.ModTime != prevInfo.ModTime || currentInfo.Size != prevInfo.Size {
changed = true
w.logDebug("File changed: %s", path)
}
}
return nil return nil
}) })
@ -133,55 +149,27 @@ func (w *DirectoryWatcher) checkForChanges() (bool, error) {
return false, err return false, err
} }
// Compare with previous state // Check for deleted files (only if we haven't already detected a change)
w.filesMu.RLock() if !changed && len(newFiles) != prevFileCount {
previousFiles := w.files w.filesMu.RLock()
w.filesMu.RUnlock() for path := range w.files {
if _, exists := newFiles[path]; !exists {
// Check for different file count (quick check) changed = true
if len(currentFiles) != len(previousFiles) { w.logDebug("File deleted: %s", path)
w.logDebug("File count changed: %d -> %d", len(previousFiles), len(currentFiles)) break
w.updateFiles(currentFiles) }
return true, nil }
w.filesMu.RUnlock()
} }
// Check for modified, added, or removed files // Update files map if changed
for path, currentInfo := range currentFiles { if changed {
prevInfo, exists := previousFiles[path] w.filesMu.Lock()
if !exists { w.files = newFiles
// New file w.filesMu.Unlock()
w.logDebug("New file detected: %s", path)
w.updateFiles(currentFiles)
return true, nil
}
if currentInfo.ModTime != prevInfo.ModTime || currentInfo.Size != prevInfo.Size {
// File modified
w.logDebug("File modified: %s", path)
w.updateFiles(currentFiles)
return true, nil
}
} }
// Check for deleted files return changed, nil
for path := range previousFiles {
if _, exists := currentFiles[path]; !exists {
// File deleted
w.logDebug("File deleted: %s", path)
w.updateFiles(currentFiles)
return true, nil
}
}
// No changes detected
return false, nil
}
// updateFiles updates the internal file list
func (w *DirectoryWatcher) updateFiles(newFiles map[string]FileInfo) {
w.filesMu.Lock()
w.files = newFiles
w.filesMu.Unlock()
} }
// notifyChange triggers the callback with debouncing // notifyChange triggers the callback with debouncing
@ -189,8 +177,8 @@ func (w *DirectoryWatcher) notifyChange() {
w.debounceMu.Lock() w.debounceMu.Lock()
defer w.debounceMu.Unlock() defer w.debounceMu.Unlock()
// Reset timer if already debouncing
if w.debouncing { if w.debouncing {
// Reset timer if already debouncing
if w.debounceTimer != nil { if w.debounceTimer != nil {
w.debounceTimer.Stop() w.debounceTimer.Stop()
} }

View File

@ -4,47 +4,33 @@ import (
"sync" "sync"
"time" "time"
"Moonshark/core/logger" "Moonshark/core/utils/logger"
) )
// Default polling intervals // Default polling interval
const ( const (
defaultPollInterval = 1 * time.Second // Initial polling interval defaultPollInterval = 1 * time.Second
extendedPollInterval = 5 * time.Second // Extended polling interval after inactivity
inactivityThreshold = 10 * time.Minute // Time before extending polling interval
) )
// WatcherManager coordinates file watching across multiple directories // WatcherManager coordinates file watching across multiple directories
type WatcherManager struct { type WatcherManager struct {
// Registry of directories and their watchers
watchers map[string]*DirectoryWatcher watchers map[string]*DirectoryWatcher
mu sync.RWMutex mu sync.RWMutex
// Shared polling state
pollInterval time.Duration
adaptive bool
lastActivity time.Time
// Control channels
done chan struct{} done chan struct{}
ticker *time.Ticker ticker *time.Ticker
// Wait group for shutdown coordination
wg sync.WaitGroup wg sync.WaitGroup
} }
// NewWatcherManager creates a new watcher manager // NewWatcherManager creates a new watcher manager
func NewWatcherManager(adaptive bool) *WatcherManager { func NewWatcherManager() *WatcherManager {
manager := &WatcherManager{ manager := &WatcherManager{
watchers: make(map[string]*DirectoryWatcher), watchers: make(map[string]*DirectoryWatcher),
pollInterval: defaultPollInterval, done: make(chan struct{}),
adaptive: adaptive,
lastActivity: time.Now(),
done: make(chan struct{}),
} }
// Start the polling loop manager.ticker = time.NewTicker(defaultPollInterval)
manager.ticker = time.NewTicker(manager.pollInterval)
manager.wg.Add(1) manager.wg.Add(1)
go manager.pollLoop() go manager.pollLoop()
@ -86,30 +72,7 @@ func (m *WatcherManager) pollLoop() {
for { for {
select { select {
case <-m.ticker.C: case <-m.ticker.C:
anyActivity := m.checkAllDirectories() m.checkAllDirectories()
// Update polling interval based on activity
if m.adaptive {
if anyActivity {
// Activity detected, reset to fast polling
m.lastActivity = time.Now()
if m.pollInterval > defaultPollInterval {
m.pollInterval = defaultPollInterval
m.ticker.Reset(m.pollInterval)
logger.Debug("[WatcherManager] Reset to base polling interval: %v", m.pollInterval)
}
} else {
// No activity, consider slowing down polling
inactiveDuration := time.Since(m.lastActivity)
if m.pollInterval == defaultPollInterval && inactiveDuration > inactivityThreshold {
m.pollInterval = extendedPollInterval
m.ticker.Reset(m.pollInterval)
logger.Debug("[WatcherManager] Extended polling interval to: %v after %v of inactivity",
m.pollInterval, inactiveDuration.Round(time.Minute))
}
}
}
case <-m.done: case <-m.done:
return return
} }
@ -117,11 +80,10 @@ func (m *WatcherManager) pollLoop() {
} }
// checkAllDirectories polls all registered directories for changes // checkAllDirectories polls all registered directories for changes
func (m *WatcherManager) checkAllDirectories() bool { func (m *WatcherManager) checkAllDirectories() {
m.mu.RLock() m.mu.RLock()
defer m.mu.RUnlock() defer m.mu.RUnlock()
anyActivity := false
for _, watcher := range m.watchers { for _, watcher := range m.watchers {
changed, err := watcher.checkForChanges() changed, err := watcher.checkForChanges()
if err != nil { if err != nil {
@ -130,10 +92,7 @@ func (m *WatcherManager) checkAllDirectories() bool {
} }
if changed { if changed {
anyActivity = true
watcher.notifyChange() watcher.notifyChange()
} }
} }
return anyActivity
} }

View File

@ -7,7 +7,7 @@ import (
"syscall" "syscall"
"Moonshark/core" "Moonshark/core"
"Moonshark/core/logger" "Moonshark/core/utils/logger"
) )
func main() { func main() {