Improve portable launch, forge persistence, and operator auth UX.

Persist build extra_files for Build Manager history, print dashboard login on every start, add libp2p for Mesh P2P forge, defer WebSocket until login, and split devrun.bat from LAUNCH.bat with USB deck auto-detection.
This commit is contained in:
AetherForge
2026-05-31 18:56:43 -07:00
parent 2f528229f2
commit feba06e008
80 changed files with 2897 additions and 675 deletions

View File

@@ -1,9 +1,11 @@
package maintenance
import (
"context"
"log"
"os"
"path/filepath"
"sync"
"time"
"crypto-miner-server/internal/db"
@@ -15,21 +17,47 @@ var retentionTickInterval = 6 * time.Hour
// runRetentionFn is the work function invoked by StartRetentionJobs (overridable in tests).
var runRetentionFn = runRetention
var (
retentionMu sync.Mutex
retentionCancel context.CancelFunc
)
// StartRetentionJobs purges old stats and build artifacts on an interval.
func StartRetentionJobs(database *db.Database, dataDir string, statsHours, buildDays int) {
if statsHours <= 0 && buildDays <= 0 {
return
}
ctx, cancel := context.WithCancel(context.Background())
retentionMu.Lock()
retentionCancel = cancel
retentionMu.Unlock()
go func() {
runRetentionFn(database, dataDir, statsHours, buildDays)
ticker := time.NewTicker(retentionTickInterval)
defer ticker.Stop()
for range ticker.C {
runRetentionFn(database, dataDir, statsHours, buildDays)
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
runRetentionFn(database, dataDir, statsHours, buildDays)
}
}
}()
}
// StopRetentionJobs stops the background retention loop started by StartRetentionJobs.
func StopRetentionJobs() {
retentionMu.Lock()
cancel := retentionCancel
retentionCancel = nil
retentionMu.Unlock()
if cancel != nil {
cancel()
}
}
func runRetention(database *db.Database, dataDir string, statsHours, buildDays int) {
if statsHours > 0 {
cutoff := time.Now().Add(-time.Duration(statsHours) * time.Hour)