refactor: propagate context.Context through call chains
CI / test (pull_request) Successful in 1m56s
CI / lint (pull_request) Successful in 1m17s
CI / vulncheck (pull_request) Successful in 56s

Thread context.Context from callers instead of creating
context.Background() at every call site. Engine stores its
lifecycle ctx for use by triggerAlert goroutines. TUI Model
carries ctx for store operations in Cmd closures. CLI commands
create a root ctx and thread it through openStore, seed
functions, and init methods.

Only two intentional context.Background() remain in non-root
positions: engine constructor default (overridden by Start)
and drainWrites (parent already cancelled at shutdown).
This commit was merged in pull request #155.
This commit is contained in:
2026-06-27 19:43:44 -04:00
parent 8f16a09da1
commit a5fd3aec90
14 changed files with 108 additions and 89 deletions
+7 -7
View File
@@ -19,8 +19,8 @@ type AlertHealth struct {
// InitAlertHealth restores persisted alert send health so the dashboard shows real
// "last sent" / health state on startup instead of resetting every channel to "never".
func (e *Engine) InitAlertHealth() {
records, err := e.db.LoadAlertHealth(context.Background())
func (e *Engine) InitAlertHealth(ctx context.Context) {
records, err := e.db.LoadAlertHealth(ctx)
if err != nil {
return
}
@@ -198,7 +198,7 @@ func (e *Engine) triggerAlert(alertID int, title, message string) {
if alertID <= 0 {
return
}
cfg, err := e.db.GetAlert(context.Background(), alertID)
cfg, err := e.db.GetAlert(e.ctx, alertID)
if err != nil {
e.AddLog(fmt.Sprintf("Failed to load alert config %d: %v", alertID, err))
return
@@ -206,7 +206,7 @@ func (e *Engine) triggerAlert(alertID int, title, message string) {
provider := alert.GetProvider(cfg)
if provider != nil {
go func() {
ctx, cancel := context.WithTimeout(context.Background(), alertSendTimeout)
ctx, cancel := context.WithTimeout(e.ctx, alertSendTimeout)
defer cancel()
if err := provider.Send(ctx, title, message); err != nil {
e.AddLog(fmt.Sprintf("Alert send failed (%s): %v", cfg.Name, err))
@@ -250,8 +250,8 @@ func (e *Engine) GetAlertHealth(alertID int) AlertHealth {
return e.alertHealth[alertID]
}
func (e *Engine) TestAlert(alertID int) error {
cfg, err := e.db.GetAlert(context.Background(), alertID)
func (e *Engine) TestAlert(ctx context.Context, alertID int) error {
cfg, err := e.db.GetAlert(ctx, alertID)
if err != nil {
return fmt.Errorf("failed to load alert: %w", err)
}
@@ -259,7 +259,7 @@ func (e *Engine) TestAlert(alertID int) error {
if provider == nil {
return fmt.Errorf("no provider for type %q", cfg.Type)
}
ctx, cancel := context.WithTimeout(context.Background(), alertSendTimeout)
ctx, cancel := context.WithTimeout(ctx, alertSendTimeout)
defer cancel()
err = provider.Send(ctx, "🧪 Test Alert", fmt.Sprintf("Test notification from uptop for channel '%s'.", cfg.Name))
if err != nil {