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
70 lines
1.5 KiB
Go
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)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|