From 486b425e997194b96dc60737f304a0f5023b7479 Mon Sep 17 00:00:00 2001 From: Xevion Date: Mon, 23 Jun 2025 15:16:04 -0500 Subject: [PATCH] feat: add 'start' app method, add state transition checks --- internal/app/app.go | 86 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 3 deletions(-) diff --git a/internal/app/app.go b/internal/app/app.go index 6df751d..8740fa3 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -1,6 +1,7 @@ package app import ( + "fmt" "log/slog" "sync" ) @@ -25,15 +26,55 @@ const ( func NewApp(logger *slog.Logger) *App { return &App{ logger: logger, - state: StateRunning, + state: StateStopped, } } +// Start transitions the application from Stopped or Paused to Running +func (app *App) Start() error { + app.mu.Lock() + defer app.mu.Unlock() + + switch app.state { + case StateRunning: + return fmt.Errorf("application is already running") + case StateStopped, StatePaused: + // valid states to start from, do nothing + default: + return fmt.Errorf("cannot start application from state: %s", app.state) + } + + app.logger.Info("starting application", + "action", "start", + "previous_state", app.state, + "new_state", StateRunning) + + // TODO: Implement actual start logic + // - Connect to Home Assistant WebSocket + // - Start background tasks + // - Start sensor monitoring + + app.state = StateRunning + + app.logger.Info("started successfully", + "action", "start", + "state", app.state) + + return nil +} + // Pause disconnects from the server and ceases any background tasks func (app *App) Pause() error { app.mu.Lock() defer app.mu.Unlock() + switch app.state { + case StatePaused: + return fmt.Errorf("application is already paused") + case StateStopped: + return fmt.Errorf("cannot pause application when stopped") + } + app.logger.Info("pausing application", "action", "pause", "previous_state", app.state, @@ -58,6 +99,17 @@ func (app *App) Resume() error { app.mu.Lock() defer app.mu.Unlock() + switch app.state { + case StateRunning: + return fmt.Errorf("application is already running") + case StateStopped: + return fmt.Errorf("cannot resume application when stopped, instead, start the application") + case StatePaused: + // valid state to resume from, do nothing + default: + return fmt.Errorf("cannot resume application from state: %s", app.state) + } + app.logger.Info("resuming application", "action", "resume", "previous_state", app.state, @@ -79,18 +131,37 @@ func (app *App) Resume() error { // Reload pauses the application, re-reads configuration files, then resumes func (a *App) Reload() error { + a.mu.Lock() + defer a.mu.Unlock() + + switch a.state { + case StateStopped: + return fmt.Errorf("cannot reload application when stopped") + case StatePaused: + return fmt.Errorf("cannot reload application when paused") + case StateRunning: + // valid state to reload from, do nothing + default: + return fmt.Errorf("cannot reload application from state: %s", a.state) + } + a.logger.Info("starting application reload", "action", "reload", "current_state", a.state) // Pause if not already paused - if a.state != StatePaused { + switch a.state { + case StatePaused: + // already paused, do nothing + case StateRunning: if err := a.Pause(); err != nil { a.logger.Error("failed to pause during reload", "action", "reload", "error", err) return err } + default: + return fmt.Errorf("unexpected state encountered while pausing for reload: %s", a.state) } // TODO: Implement configuration reload logic @@ -103,7 +174,7 @@ func (a *App) Reload() error { // Resume the application if err := a.Resume(); err != nil { - a.logger.Error("failed to resume after reload", + a.logger.Error("failed to resume during reload", "action", "reload", "error", err) return err @@ -128,6 +199,15 @@ func (app *App) Stop() error { app.mu.Lock() defer app.mu.Unlock() + switch app.state { + case StateStopped: + return fmt.Errorf("application is already stopped") + case StatePaused, StateRunning: + // valid state to stop from, do nothing + default: + return fmt.Errorf("unexpected state encountered while stopping application: %s", app.state) + } + app.logger.Info("stopping application", "action", "stop", "previous_state", app.state,