fetch_ml/internal/worker/lifecycle/health.go
Jeremie Fraeys 062b78cbe0
refactor: Phase 4 - Extract lifecycle types and interfaces
Created lifecycle package with foundational types for future extraction:

1. internal/worker/lifecycle/runloop.go (117 lines)
   - TaskExecutor interface for task execution contract
   - RunLoopConfig for run loop configuration
   - RunLoop type with core orchestration logic
   - MetricsRecorder and Logger interfaces for dependencies
   - Start(), Stop() methods for loop control
   - executeTask() method for task lifecycle management

2. internal/worker/lifecycle/health.go (52 lines)
   - HealthMonitor type for health tracking
   - RecordHeartbeat(), IsHealthy(), MarkUnhealthy() methods
   - Heartbeater interface for heartbeat operations
   - HeartbeatLoop() function for background heartbeats

Note: These are interface/type foundations for Phase 5.
The actual Worker struct methods remain in runloop.go until
Phase 5 when they'll migrate to use these abstractions.

Build status: Compiles successfully
2026-02-17 14:22:58 -05:00

70 lines
1.5 KiB
Go

// Package lifecycle provides worker lifecycle management types and interfaces
package lifecycle
import (
"context"
"sync"
"time"
)
// HealthMonitor tracks worker health status
type HealthMonitor struct {
lastHeartbeat time.Time
healthy bool
mu sync.RWMutex
}
// NewHealthMonitor creates a new health monitor
func NewHealthMonitor() *HealthMonitor {
return &HealthMonitor{
lastHeartbeat: time.Now(),
healthy: true,
}
}
// RecordHeartbeat updates the last heartbeat time
func (h *HealthMonitor) RecordHeartbeat() {
h.mu.Lock()
defer h.mu.Unlock()
h.lastHeartbeat = time.Now()
h.healthy = true
}
// IsHealthy returns true if the worker is healthy
func (h *HealthMonitor) IsHealthy(timeout time.Duration) bool {
h.mu.RLock()
defer h.mu.RUnlock()
return h.healthy && time.Since(h.lastHeartbeat) < timeout
}
// MarkUnhealthy marks the worker as unhealthy
func (h *HealthMonitor) MarkUnhealthy() {
h.mu.Lock()
defer h.mu.Unlock()
h.healthy = false
}
// Heartbeater defines the contract for heartbeat operations
type Heartbeater interface {
// Beat performs a single heartbeat
Beat(ctx context.Context) error
}
// HeartbeatLoop runs the heartbeat loop
func HeartbeatLoop(ctx context.Context, interval time.Duration, hb Heartbeater, onFailure func(error)) {
ticker := time.NewTicker(interval)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
if err := hb.Beat(ctx); err != nil {
if onFailure != nil {
onFailure(err)
}
}
}
}
}