Files
CHORUS/pkg/health/integration_example.go
anthonyrawlins 9bdcbe0447 Integrate BACKBEAT SDK and resolve KACHING license validation
Major integrations and fixes:
- Added BACKBEAT SDK integration for P2P operation timing
- Implemented beat-aware status tracking for distributed operations
- Added Docker secrets support for secure license management
- Resolved KACHING license validation via HTTPS/TLS
- Updated docker-compose configuration for clean stack deployment
- Disabled rollback policies to prevent deployment failures
- Added license credential storage (CHORUS-DEV-MULTI-001)

Technical improvements:
- BACKBEAT P2P operation tracking with phase management
- Enhanced configuration system with file-based secrets
- Improved error handling for license validation
- Clean separation of KACHING and CHORUS deployment stacks

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-06 07:56:26 +10:00

307 lines
9.0 KiB
Go

package health
import (
"context"
"fmt"
"net/http"
"time"
"chorus/pkg/shutdown"
)
// IntegrationExample demonstrates how to integrate health monitoring and graceful shutdown
func IntegrationExample() {
// Create logger (in real implementation, use your logging system)
logger := &defaultLogger{}
// Create shutdown manager
shutdownManager := shutdown.NewManager(30*time.Second, logger)
// Create health manager
healthManager := NewManager("node-123", "v1.0.0", logger)
// Connect health manager to shutdown manager for critical failures
healthManager.SetShutdownManager(shutdownManager)
// Register some example health checks
setupHealthChecks(healthManager)
// Create and register components for graceful shutdown
setupShutdownComponents(shutdownManager, healthManager)
// Start systems
if err := healthManager.Start(); err != nil {
logger.Error("Failed to start health manager: %v", err)
return
}
// Start health HTTP server
if err := healthManager.StartHTTPServer(8081); err != nil {
logger.Error("Failed to start health HTTP server: %v", err)
return
}
// Add shutdown hooks
setupShutdownHooks(shutdownManager, healthManager, logger)
// Start shutdown manager (begins listening for signals)
shutdownManager.Start()
logger.Info("🚀 System started with integrated health monitoring and graceful shutdown")
logger.Info("📊 Health endpoints available at:")
logger.Info(" - http://localhost:8081/health (overall health)")
logger.Info(" - http://localhost:8081/health/ready (readiness)")
logger.Info(" - http://localhost:8081/health/live (liveness)")
logger.Info(" - http://localhost:8081/health/checks (detailed checks)")
// Wait for shutdown
shutdownManager.Wait()
logger.Info("✅ System shutdown completed")
}
// setupHealthChecks registers various health checks
func setupHealthChecks(healthManager *Manager) {
// Database connectivity check (critical)
databaseCheck := CreateDatabaseCheck("primary-db", func() error {
// Simulate database ping
time.Sleep(10 * time.Millisecond)
// Return nil for healthy, error for unhealthy
return nil
})
healthManager.RegisterCheck(databaseCheck)
// Memory usage check (warning only)
memoryCheck := CreateMemoryCheck(0.85) // Alert if > 85%
healthManager.RegisterCheck(memoryCheck)
// Disk space check (warning only)
diskCheck := CreateDiskSpaceCheck("/var/lib/CHORUS", 0.90) // Alert if > 90%
healthManager.RegisterCheck(diskCheck)
// Custom application-specific health check
customCheck := &HealthCheck{
Name: "p2p-connectivity",
Description: "P2P network connectivity check",
Enabled: true,
Critical: true, // This is critical for P2P systems
Interval: 15 * time.Second,
Timeout: 10 * time.Second,
Checker: func(ctx context.Context) CheckResult {
// Simulate P2P connectivity check
time.Sleep(50 * time.Millisecond)
// Simulate occasionally failing check
connected := time.Now().Unix()%10 != 0 // Fail 10% of the time
if !connected {
return CheckResult{
Healthy: false,
Message: "No P2P peers connected",
Details: map[string]interface{}{
"connected_peers": 0,
"min_peers": 1,
},
Timestamp: time.Now(),
}
}
return CheckResult{
Healthy: true,
Message: "P2P connectivity OK",
Details: map[string]interface{}{
"connected_peers": 5,
"min_peers": 1,
},
Timestamp: time.Now(),
}
},
}
healthManager.RegisterCheck(customCheck)
// Election system health check
electionCheck := &HealthCheck{
Name: "election-system",
Description: "Election system health check",
Enabled: true,
Critical: false, // Elections can be temporarily unhealthy
Interval: 30 * time.Second,
Timeout: 5 * time.Second,
Checker: func(ctx context.Context) CheckResult {
// Simulate election system check
healthy := true
message := "Election system operational"
return CheckResult{
Healthy: healthy,
Message: message,
Details: map[string]interface{}{
"current_admin": "node-456",
"election_term": 42,
"last_election": time.Now().Add(-10 * time.Minute),
},
Timestamp: time.Now(),
}
},
}
healthManager.RegisterCheck(electionCheck)
}
// setupShutdownComponents registers components for graceful shutdown
func setupShutdownComponents(shutdownManager *shutdown.Manager, healthManager *Manager) {
// Register health manager for shutdown (high priority to stop health checks early)
healthComponent := shutdown.NewGenericComponent("health-manager", 10, true).
SetShutdownFunc(func(ctx context.Context) error {
return healthManager.Stop()
})
shutdownManager.Register(healthComponent)
// Simulate HTTP server
httpServer := &http.Server{Addr: ":8080"}
httpComponent := shutdown.NewHTTPServerComponent("main-http-server", httpServer, 20)
shutdownManager.Register(httpComponent)
// Simulate P2P node
p2pComponent := shutdown.NewP2PNodeComponent("p2p-node", func() error {
// Simulate P2P node cleanup
time.Sleep(2 * time.Second)
return nil
}, 30)
shutdownManager.Register(p2pComponent)
// Simulate database connections
dbComponent := shutdown.NewDatabaseComponent("database-pool", func() error {
// Simulate database connection cleanup
time.Sleep(1 * time.Second)
return nil
}, 40)
shutdownManager.Register(dbComponent)
// Simulate worker pool
workerStopCh := make(chan struct{})
workerComponent := shutdown.NewWorkerPoolComponent("background-workers", workerStopCh, 5, 50)
shutdownManager.Register(workerComponent)
// Simulate monitoring/metrics system
monitoringComponent := shutdown.NewMonitoringComponent("metrics-system", func() error {
// Simulate metrics system cleanup
time.Sleep(500 * time.Millisecond)
return nil
}, 60)
shutdownManager.Register(monitoringComponent)
}
// setupShutdownHooks adds hooks for different shutdown phases
func setupShutdownHooks(shutdownManager *shutdown.Manager, healthManager *Manager, logger shutdown.Logger) {
// Pre-shutdown hook: Mark system as stopping
shutdownManager.AddHook(shutdown.PhasePreShutdown, func(ctx context.Context) error {
logger.Info("🔄 Pre-shutdown: Marking system as stopping")
// Update health status to stopping
status := healthManager.GetStatus()
status.Status = StatusStopping
status.Message = "System is shutting down"
return nil
})
// Shutdown hook: Log progress
shutdownManager.AddHook(shutdown.PhaseShutdown, func(ctx context.Context) error {
logger.Info("🔄 Shutdown phase: Components are being shut down")
return nil
})
// Post-shutdown hook: Final health status update and cleanup
shutdownManager.AddHook(shutdown.PhasePostShutdown, func(ctx context.Context) error {
logger.Info("🔄 Post-shutdown: Performing final cleanup")
// Any final cleanup that needs to happen after components are shut down
return nil
})
// Cleanup hook: Final logging and state persistence
shutdownManager.AddHook(shutdown.PhaseCleanup, func(ctx context.Context) error {
logger.Info("🔄 Cleanup: Finalizing shutdown process")
// Save any final state, flush logs, etc.
return nil
})
}
// HealthAwareComponent is an example of how to create components that integrate with health monitoring
type HealthAwareComponent struct {
name string
healthManager *Manager
checkName string
isRunning bool
stopCh chan struct{}
}
// NewHealthAwareComponent creates a component that registers its own health check
func NewHealthAwareComponent(name string, healthManager *Manager) *HealthAwareComponent {
comp := &HealthAwareComponent{
name: name,
healthManager: healthManager,
checkName: fmt.Sprintf("%s-health", name),
stopCh: make(chan struct{}),
}
// Register health check for this component
healthCheck := &HealthCheck{
Name: comp.checkName,
Description: fmt.Sprintf("Health check for %s component", name),
Enabled: true,
Critical: false,
Interval: 30 * time.Second,
Timeout: 10 * time.Second,
Checker: func(ctx context.Context) CheckResult {
if comp.isRunning {
return CheckResult{
Healthy: true,
Message: fmt.Sprintf("%s is running normally", comp.name),
Timestamp: time.Now(),
}
}
return CheckResult{
Healthy: false,
Message: fmt.Sprintf("%s is not running", comp.name),
Timestamp: time.Now(),
}
},
}
healthManager.RegisterCheck(healthCheck)
return comp
}
// Start starts the component
func (c *HealthAwareComponent) Start() error {
c.isRunning = true
return nil
}
// Name returns the component name
func (c *HealthAwareComponent) Name() string {
return c.name
}
// Priority returns the shutdown priority
func (c *HealthAwareComponent) Priority() int {
return 50
}
// CanForceStop returns whether the component can be force-stopped
func (c *HealthAwareComponent) CanForceStop() bool {
return true
}
// Shutdown gracefully shuts down the component
func (c *HealthAwareComponent) Shutdown(ctx context.Context) error {
c.isRunning = false
close(c.stopCh)
// Unregister health check
c.healthManager.UnregisterCheck(c.checkName)
return nil
}