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"
"time"
"Moonshark/core/config"
"Moonshark/core/http"
"Moonshark/core/logger"
"Moonshark/core/routers"
"Moonshark/core/runner"
"Moonshark/core/sessions"
"Moonshark/core/utils"
"Moonshark/core/utils/config"
"Moonshark/core/utils/logger"
"Moonshark/core/watchers"
)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,8 +7,8 @@ import (
"strings"
"time"
"Moonshark/core/config"
"Moonshark/core/metadata"
"Moonshark/core/utils/config"
)
// ComponentStats holds stats from various system components
@ -26,7 +26,7 @@ type SystemStats struct {
Memory runtime.MemStats
Components ComponentStats
Version string
Config *config.Config // Configuration information
Config *config.Config
}
// 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.
// Returns any error encountered during directory creation.
func EnsureDir(path string) error {
// Clean the path to handle any malformed input
path = filepath.Clean(path)
// Check if the directory exists
info, err := os.Stat(path)
// If no error, check if it's a directory
if err == nil {
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) {
return err
}
// Create the directory with default permissions (0755)
return os.MkdirAll(path, 0755)
}

View File

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

View File

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

View File

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

View File

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

View File

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