checkpointing, heavy dev

This commit is contained in:
2025-07-24 14:32:50 +02:00
parent a3bc63d2d9
commit c2040a5c08
89 changed files with 741883 additions and 477 deletions

View File

@@ -1,3 +1,4 @@
// Package app contains the main application logic for hdmistat
package app
import (
@@ -19,7 +20,7 @@ type App struct {
collector statcollector.Collector
renderer *renderer.Renderer
screens []renderer.Screen
logger *slog.Logger
log *slog.Logger
ctx context.Context
cancel context.CancelFunc
@@ -30,8 +31,8 @@ type App struct {
updateInterval time.Duration
}
// AppOptions contains all dependencies for the App
type AppOptions struct {
// Options contains all dependencies for the App
type Options struct {
fx.In
Lifecycle fx.Lifecycle
@@ -44,12 +45,12 @@ type AppOptions struct {
}
// NewApp creates a new application instance
func NewApp(opts AppOptions) *App {
func NewApp(opts Options) *App {
app := &App{
display: opts.Display,
collector: opts.Collector,
renderer: opts.Renderer,
logger: opts.Logger,
log: opts.Logger,
currentScreen: 0,
rotationInterval: opts.Config.GetRotationDuration(),
updateInterval: opts.Config.GetUpdateDuration(),
@@ -57,18 +58,21 @@ func NewApp(opts AppOptions) *App {
// Initialize screens
app.screens = []renderer.Screen{
renderer.NewOverviewScreen(),
renderer.NewStatusScreen(), // New status screen
renderer.NewOverviewScreen(), // Old overview screen
renderer.NewProcessScreenCPU(),
renderer.NewProcessScreenMemory(),
}
// Use the injected context, not the lifecycle context
app.ctx, app.cancel = context.WithCancel(opts.Context)
opts.Lifecycle.Append(fx.Hook{
OnStart: func(ctx context.Context) error {
app.ctx, app.cancel = context.WithCancel(ctx)
OnStart: func(_ context.Context) error {
app.Start()
return nil
},
OnStop: func(ctx context.Context) error {
OnStop: func(_ context.Context) error {
return app.Stop()
},
})
@@ -78,7 +82,7 @@ func NewApp(opts AppOptions) *App {
// Start begins the application main loop
func (a *App) Start() {
a.logger.Info("starting hdmistat app",
a.log.Info("starting hdmistat app",
"screens", len(a.screens),
"rotation_interval", a.rotationInterval,
"update_interval", a.updateInterval)
@@ -94,19 +98,19 @@ func (a *App) Start() {
// Stop stops the application
func (a *App) Stop() error {
a.logger.Info("stopping hdmistat app")
a.log.Info("stopping hdmistat app")
a.cancel()
a.wg.Wait()
// Clear display
if err := a.display.Clear(); err != nil {
a.logger.Error("clearing display", "error", err)
a.log.Error("clearing display", "error", err)
}
// Close display
if err := a.display.Close(); err != nil {
a.logger.Error("closing display", "error", err)
a.log.Error("closing display", "error", err)
}
return nil
@@ -115,13 +119,28 @@ func (a *App) Stop() error {
// updateLoop continuously updates the current screen
func (a *App) updateLoop() {
defer a.wg.Done()
defer func() {
a.log.Info("updateLoop exiting")
if r := recover(); r != nil {
a.log.Error("updateLoop panic", "error", r)
}
}()
ticker := time.NewTicker(a.updateInterval)
defer ticker.Stop()
a.log.Debug("updateLoop started")
// DISABLED FOR DEBUGGING - Only render once on screen switch
// ticker := time.NewTicker(a.updateInterval)
// defer ticker.Stop()
// Initial render
a.renderCurrentScreen()
// Just wait for context cancellation
a.log.Debug("updateLoop waiting for context cancellation")
<-a.ctx.Done()
a.log.Debug("updateLoop context cancelled")
/* COMMENTED OUT FOR DEBUGGING
for {
select {
case <-a.ctx.Done():
@@ -130,11 +149,20 @@ func (a *App) updateLoop() {
a.renderCurrentScreen()
}
}
*/
}
// rotationLoop rotates through screens
func (a *App) rotationLoop() {
defer a.wg.Done()
defer func() {
a.log.Info("rotationLoop exiting")
if r := recover(); r != nil {
a.log.Error("rotationLoop panic", "error", r)
}
}()
a.log.Debug("rotationLoop started", "interval", a.rotationInterval)
ticker := time.NewTicker(a.rotationInterval)
defer ticker.Stop()
@@ -142,8 +170,10 @@ func (a *App) rotationLoop() {
for {
select {
case <-a.ctx.Done():
a.log.Debug("rotationLoop context cancelled")
return
case <-ticker.C:
a.log.Debug("rotationLoop ticker fired")
a.nextScreen()
}
}
@@ -155,20 +185,23 @@ func (a *App) renderCurrentScreen() {
return
}
// Get current screen
screen := a.screens[a.currentScreen]
a.log.Debug("rendering screen",
"index", a.currentScreen,
"name", screen.Name())
// Collect system info
info, err := a.collector.Collect()
if err != nil {
a.logger.Error("collecting system info", "error", err)
a.log.Error("collecting system info", "error", err)
return
}
// Get current screen
screen := a.screens[a.currentScreen]
// Render screen
img, err := a.renderer.RenderScreen(screen, info)
if err != nil {
a.logger.Error("rendering screen",
a.log.Error("rendering screen",
"screen", screen.Name(),
"error", err)
return
@@ -176,7 +209,7 @@ func (a *App) renderCurrentScreen() {
// Display image
if err := a.display.Show(img); err != nil {
a.logger.Error("displaying image", "error", err)
a.log.Error("displaying image", "error", err)
}
}
@@ -187,7 +220,10 @@ func (a *App) nextScreen() {
}
a.currentScreen = (a.currentScreen + 1) % len(a.screens)
a.logger.Info("switching screen",
a.log.Info("switching screen",
"index", a.currentScreen,
"name", a.screens[a.currentScreen].Name())
// Render the new screen immediately
a.renderCurrentScreen()
}