fix: resolve all compilation issues across transport and lifecycle packages
- Fixed duplicate type declarations in transport package - Removed unused variables in lifecycle and dependency injection - Fixed big.Int arithmetic operations in uniswap contracts - Added missing methods to MetricsCollector (IncrementCounter, RecordLatency, etc.) - Fixed jitter calculation in TCP transport retry logic - Updated ComponentHealth field access to use transport type - Ensured all core packages build successfully All major compilation errors resolved: ✅ Transport package builds clean ✅ Lifecycle package builds clean ✅ Main MEV bot application builds clean ✅ Fixed method signature mismatches ✅ Resolved type conflicts and duplications 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
838
pkg/lifecycle/module_registry.go
Normal file
838
pkg/lifecycle/module_registry.go
Normal file
@@ -0,0 +1,838 @@
|
||||
package lifecycle
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ModuleRegistry manages the registration, discovery, and lifecycle of system modules
|
||||
type ModuleRegistry struct {
|
||||
modules map[string]*RegisteredModule
|
||||
modulesByType map[reflect.Type][]*RegisteredModule
|
||||
dependencies map[string][]string
|
||||
startOrder []string
|
||||
stopOrder []string
|
||||
state RegistryState
|
||||
eventBus EventBus
|
||||
healthMonitor HealthMonitor
|
||||
config RegistryConfig
|
||||
mu sync.RWMutex
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
// RegisteredModule represents a module in the registry
|
||||
type RegisteredModule struct {
|
||||
ID string
|
||||
Name string
|
||||
Type reflect.Type
|
||||
Instance Module
|
||||
Config ModuleConfig
|
||||
Dependencies []string
|
||||
State ModuleState
|
||||
Metadata map[string]interface{}
|
||||
StartTime time.Time
|
||||
StopTime time.Time
|
||||
HealthStatus ModuleHealth
|
||||
Metrics ModuleMetrics
|
||||
Created time.Time
|
||||
Version string
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
// Module interface that all modules must implement
|
||||
type Module interface {
|
||||
// Core lifecycle methods
|
||||
Initialize(ctx context.Context, config ModuleConfig) error
|
||||
Start(ctx context.Context) error
|
||||
Stop(ctx context.Context) error
|
||||
Pause(ctx context.Context) error
|
||||
Resume(ctx context.Context) error
|
||||
|
||||
// Module information
|
||||
GetID() string
|
||||
GetName() string
|
||||
GetVersion() string
|
||||
GetDependencies() []string
|
||||
|
||||
// Health and status
|
||||
GetHealth() ModuleHealth
|
||||
GetState() ModuleState
|
||||
GetMetrics() ModuleMetrics
|
||||
}
|
||||
|
||||
// ModuleState represents the current state of a module
|
||||
type ModuleState string
|
||||
|
||||
const (
|
||||
StateUninitialized ModuleState = "uninitialized"
|
||||
StateInitialized ModuleState = "initialized"
|
||||
StateStarting ModuleState = "starting"
|
||||
StateRunning ModuleState = "running"
|
||||
StatePausing ModuleState = "pausing"
|
||||
StatePaused ModuleState = "paused"
|
||||
StateResuming ModuleState = "resuming"
|
||||
StateStopping ModuleState = "stopping"
|
||||
StateStopped ModuleState = "stopped"
|
||||
StateFailed ModuleState = "failed"
|
||||
)
|
||||
|
||||
// RegistryState represents the state of the entire registry
|
||||
type RegistryState string
|
||||
|
||||
const (
|
||||
RegistryUninitialized RegistryState = "uninitialized"
|
||||
RegistryInitialized RegistryState = "initialized"
|
||||
RegistryStarting RegistryState = "starting"
|
||||
RegistryRunning RegistryState = "running"
|
||||
RegistryStopping RegistryState = "stopping"
|
||||
RegistryStopped RegistryState = "stopped"
|
||||
RegistryFailed RegistryState = "failed"
|
||||
)
|
||||
|
||||
// ModuleConfig contains configuration for a module
|
||||
type ModuleConfig struct {
|
||||
Settings map[string]interface{} `json:"settings"`
|
||||
Enabled bool `json:"enabled"`
|
||||
StartTimeout time.Duration `json:"start_timeout"`
|
||||
StopTimeout time.Duration `json:"stop_timeout"`
|
||||
HealthCheckInterval time.Duration `json:"health_check_interval"`
|
||||
MaxRestarts int `json:"max_restarts"`
|
||||
RestartDelay time.Duration `json:"restart_delay"`
|
||||
CriticalModule bool `json:"critical_module"`
|
||||
}
|
||||
|
||||
// ModuleHealth represents the health status of a module
|
||||
type ModuleHealth struct {
|
||||
Status HealthStatus `json:"status"`
|
||||
LastCheck time.Time `json:"last_check"`
|
||||
Message string `json:"message"`
|
||||
Details map[string]interface{} `json:"details"`
|
||||
Uptime time.Duration `json:"uptime"`
|
||||
RestartCount int `json:"restart_count"`
|
||||
}
|
||||
|
||||
// HealthStatus represents health check results
|
||||
type HealthStatus string
|
||||
|
||||
const (
|
||||
HealthHealthy HealthStatus = "healthy"
|
||||
HealthDegraded HealthStatus = "degraded"
|
||||
HealthUnhealthy HealthStatus = "unhealthy"
|
||||
HealthUnknown HealthStatus = "unknown"
|
||||
)
|
||||
|
||||
// ModuleMetrics contains performance metrics for a module
|
||||
type ModuleMetrics struct {
|
||||
StartupTime time.Duration `json:"startup_time"`
|
||||
ShutdownTime time.Duration `json:"shutdown_time"`
|
||||
MemoryUsage int64 `json:"memory_usage"`
|
||||
CPUUsage float64 `json:"cpu_usage"`
|
||||
RequestCount int64 `json:"request_count"`
|
||||
ErrorCount int64 `json:"error_count"`
|
||||
LastActivity time.Time `json:"last_activity"`
|
||||
CustomMetrics map[string]interface{} `json:"custom_metrics"`
|
||||
}
|
||||
|
||||
// RegistryConfig configures the module registry
|
||||
type RegistryConfig struct {
|
||||
StartTimeout time.Duration `json:"start_timeout"`
|
||||
StopTimeout time.Duration `json:"stop_timeout"`
|
||||
HealthCheckInterval time.Duration `json:"health_check_interval"`
|
||||
EnableMetrics bool `json:"enable_metrics"`
|
||||
EnableHealthMonitor bool `json:"enable_health_monitor"`
|
||||
ParallelStartup bool `json:"parallel_startup"`
|
||||
ParallelShutdown bool `json:"parallel_shutdown"`
|
||||
FailureRecovery bool `json:"failure_recovery"`
|
||||
AutoRestart bool `json:"auto_restart"`
|
||||
MaxRestartAttempts int `json:"max_restart_attempts"`
|
||||
}
|
||||
|
||||
// EventBus interface for module events
|
||||
type EventBus interface {
|
||||
Publish(event ModuleEvent) error
|
||||
Subscribe(eventType EventType, handler EventHandler) error
|
||||
}
|
||||
|
||||
// HealthMonitor interface for health monitoring
|
||||
type HealthMonitor interface {
|
||||
CheckHealth(module *RegisteredModule) ModuleHealth
|
||||
StartMonitoring(module *RegisteredModule) error
|
||||
StopMonitoring(moduleID string) error
|
||||
GetHealthStatus() map[string]ModuleHealth
|
||||
}
|
||||
|
||||
// ModuleEvent represents an event in the module lifecycle
|
||||
type ModuleEvent struct {
|
||||
Type EventType `json:"type"`
|
||||
ModuleID string `json:"module_id"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Data map[string]interface{} `json:"data"`
|
||||
Error error `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// EventType defines types of module events
|
||||
type EventType string
|
||||
|
||||
const (
|
||||
EventModuleRegistered EventType = "module_registered"
|
||||
EventModuleUnregistered EventType = "module_unregistered"
|
||||
EventModuleInitialized EventType = "module_initialized"
|
||||
EventModuleStarted EventType = "module_started"
|
||||
EventModuleStopped EventType = "module_stopped"
|
||||
EventModulePaused EventType = "module_paused"
|
||||
EventModuleResumed EventType = "module_resumed"
|
||||
EventModuleFailed EventType = "module_failed"
|
||||
EventModuleRestarted EventType = "module_restarted"
|
||||
EventHealthCheck EventType = "health_check"
|
||||
)
|
||||
|
||||
// EventHandler handles module events
|
||||
type EventHandler func(event ModuleEvent) error
|
||||
|
||||
// NewModuleRegistry creates a new module registry
|
||||
func NewModuleRegistry(config RegistryConfig) *ModuleRegistry {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
registry := &ModuleRegistry{
|
||||
modules: make(map[string]*RegisteredModule),
|
||||
modulesByType: make(map[reflect.Type][]*RegisteredModule),
|
||||
dependencies: make(map[string][]string),
|
||||
config: config,
|
||||
state: RegistryUninitialized,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
}
|
||||
|
||||
// Set default configuration
|
||||
if registry.config.StartTimeout == 0 {
|
||||
registry.config.StartTimeout = 30 * time.Second
|
||||
}
|
||||
if registry.config.StopTimeout == 0 {
|
||||
registry.config.StopTimeout = 15 * time.Second
|
||||
}
|
||||
if registry.config.HealthCheckInterval == 0 {
|
||||
registry.config.HealthCheckInterval = 30 * time.Second
|
||||
}
|
||||
|
||||
return registry
|
||||
}
|
||||
|
||||
// Register registers a new module with the registry
|
||||
func (mr *ModuleRegistry) Register(module Module, config ModuleConfig) error {
|
||||
mr.mu.Lock()
|
||||
defer mr.mu.Unlock()
|
||||
|
||||
id := module.GetID()
|
||||
if _, exists := mr.modules[id]; exists {
|
||||
return fmt.Errorf("module already registered: %s", id)
|
||||
}
|
||||
|
||||
moduleType := reflect.TypeOf(module)
|
||||
registered := &RegisteredModule{
|
||||
ID: id,
|
||||
Name: module.GetName(),
|
||||
Type: moduleType,
|
||||
Instance: module,
|
||||
Config: config,
|
||||
Dependencies: module.GetDependencies(),
|
||||
State: StateUninitialized,
|
||||
Metadata: make(map[string]interface{}),
|
||||
HealthStatus: ModuleHealth{Status: HealthUnknown},
|
||||
Created: time.Now(),
|
||||
Version: module.GetVersion(),
|
||||
}
|
||||
|
||||
mr.modules[id] = registered
|
||||
mr.modulesByType[moduleType] = append(mr.modulesByType[moduleType], registered)
|
||||
mr.dependencies[id] = module.GetDependencies()
|
||||
|
||||
// Publish event
|
||||
if mr.eventBus != nil {
|
||||
mr.eventBus.Publish(ModuleEvent{
|
||||
Type: EventModuleRegistered,
|
||||
ModuleID: id,
|
||||
Timestamp: time.Now(),
|
||||
Data: map[string]interface{}{
|
||||
"name": module.GetName(),
|
||||
"version": module.GetVersion(),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unregister removes a module from the registry
|
||||
func (mr *ModuleRegistry) Unregister(moduleID string) error {
|
||||
mr.mu.Lock()
|
||||
defer mr.mu.Unlock()
|
||||
|
||||
registered, exists := mr.modules[moduleID]
|
||||
if !exists {
|
||||
return fmt.Errorf("module not found: %s", moduleID)
|
||||
}
|
||||
|
||||
// Stop module if running
|
||||
if registered.State == StateRunning {
|
||||
if err := mr.stopModule(registered); err != nil {
|
||||
return fmt.Errorf("failed to stop module before unregistering: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove from type index
|
||||
moduleType := registered.Type
|
||||
typeModules := mr.modulesByType[moduleType]
|
||||
for i, mod := range typeModules {
|
||||
if mod.ID == moduleID {
|
||||
mr.modulesByType[moduleType] = append(typeModules[:i], typeModules[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Remove from maps
|
||||
delete(mr.modules, moduleID)
|
||||
delete(mr.dependencies, moduleID)
|
||||
|
||||
// Publish event
|
||||
if mr.eventBus != nil {
|
||||
mr.eventBus.Publish(ModuleEvent{
|
||||
Type: EventModuleUnregistered,
|
||||
ModuleID: moduleID,
|
||||
Timestamp: time.Now(),
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get retrieves a module by ID
|
||||
func (mr *ModuleRegistry) Get(moduleID string) (Module, error) {
|
||||
mr.mu.RLock()
|
||||
defer mr.mu.RUnlock()
|
||||
|
||||
registered, exists := mr.modules[moduleID]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("module not found: %s", moduleID)
|
||||
}
|
||||
|
||||
return registered.Instance, nil
|
||||
}
|
||||
|
||||
// GetByType retrieves all modules of a specific type
|
||||
func (mr *ModuleRegistry) GetByType(moduleType reflect.Type) []Module {
|
||||
mr.mu.RLock()
|
||||
defer mr.mu.RUnlock()
|
||||
|
||||
registeredModules := mr.modulesByType[moduleType]
|
||||
modules := make([]Module, len(registeredModules))
|
||||
for i, registered := range registeredModules {
|
||||
modules[i] = registered.Instance
|
||||
}
|
||||
|
||||
return modules
|
||||
}
|
||||
|
||||
// List returns all registered module IDs
|
||||
func (mr *ModuleRegistry) List() []string {
|
||||
mr.mu.RLock()
|
||||
defer mr.mu.RUnlock()
|
||||
|
||||
ids := make([]string, 0, len(mr.modules))
|
||||
for id := range mr.modules {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
|
||||
return ids
|
||||
}
|
||||
|
||||
// GetState returns the current state of a module
|
||||
func (mr *ModuleRegistry) GetState(moduleID string) (ModuleState, error) {
|
||||
mr.mu.RLock()
|
||||
defer mr.mu.RUnlock()
|
||||
|
||||
registered, exists := mr.modules[moduleID]
|
||||
if !exists {
|
||||
return "", fmt.Errorf("module not found: %s", moduleID)
|
||||
}
|
||||
|
||||
return registered.State, nil
|
||||
}
|
||||
|
||||
// GetRegistryState returns the current state of the registry
|
||||
func (mr *ModuleRegistry) GetRegistryState() RegistryState {
|
||||
mr.mu.RLock()
|
||||
defer mr.mu.RUnlock()
|
||||
return mr.state
|
||||
}
|
||||
|
||||
// Initialize initializes all registered modules
|
||||
func (mr *ModuleRegistry) Initialize(ctx context.Context) error {
|
||||
mr.mu.Lock()
|
||||
defer mr.mu.Unlock()
|
||||
|
||||
if mr.state != RegistryUninitialized {
|
||||
return fmt.Errorf("registry already initialized")
|
||||
}
|
||||
|
||||
mr.state = RegistryInitialized
|
||||
|
||||
// Calculate start order based on dependencies
|
||||
startOrder, err := mr.calculateStartOrder()
|
||||
if err != nil {
|
||||
mr.state = RegistryFailed
|
||||
return fmt.Errorf("failed to calculate start order: %w", err)
|
||||
}
|
||||
mr.startOrder = startOrder
|
||||
|
||||
// Calculate stop order (reverse of start order)
|
||||
mr.stopOrder = make([]string, len(startOrder))
|
||||
for i, id := range startOrder {
|
||||
mr.stopOrder[len(startOrder)-1-i] = id
|
||||
}
|
||||
|
||||
// Initialize all modules
|
||||
for _, moduleID := range mr.startOrder {
|
||||
registered := mr.modules[moduleID]
|
||||
if err := mr.initializeModule(ctx, registered); err != nil {
|
||||
mr.state = RegistryFailed
|
||||
return fmt.Errorf("failed to initialize module %s: %w", moduleID, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// StartAll starts all registered modules in dependency order
|
||||
func (mr *ModuleRegistry) StartAll(ctx context.Context) error {
|
||||
mr.mu.Lock()
|
||||
defer mr.mu.Unlock()
|
||||
|
||||
if mr.state != RegistryInitialized && mr.state != RegistryStopped {
|
||||
return fmt.Errorf("invalid registry state for start: %s", mr.state)
|
||||
}
|
||||
|
||||
mr.state = RegistryStarting
|
||||
|
||||
if mr.config.ParallelStartup {
|
||||
return mr.startAllParallel(ctx)
|
||||
} else {
|
||||
return mr.startAllSequential(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
// StopAll stops all modules in reverse dependency order
|
||||
func (mr *ModuleRegistry) StopAll(ctx context.Context) error {
|
||||
mr.mu.Lock()
|
||||
defer mr.mu.Unlock()
|
||||
|
||||
if mr.state != RegistryRunning {
|
||||
return fmt.Errorf("invalid registry state for stop: %s", mr.state)
|
||||
}
|
||||
|
||||
mr.state = RegistryStopping
|
||||
|
||||
if mr.config.ParallelShutdown {
|
||||
return mr.stopAllParallel(ctx)
|
||||
} else {
|
||||
return mr.stopAllSequential(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
// Start starts a specific module
|
||||
func (mr *ModuleRegistry) Start(ctx context.Context, moduleID string) error {
|
||||
mr.mu.Lock()
|
||||
defer mr.mu.Unlock()
|
||||
|
||||
registered, exists := mr.modules[moduleID]
|
||||
if !exists {
|
||||
return fmt.Errorf("module not found: %s", moduleID)
|
||||
}
|
||||
|
||||
return mr.startModule(ctx, registered)
|
||||
}
|
||||
|
||||
// Stop stops a specific module
|
||||
func (mr *ModuleRegistry) Stop(ctx context.Context, moduleID string) error {
|
||||
mr.mu.Lock()
|
||||
defer mr.mu.Unlock()
|
||||
|
||||
registered, exists := mr.modules[moduleID]
|
||||
if !exists {
|
||||
return fmt.Errorf("module not found: %s", moduleID)
|
||||
}
|
||||
|
||||
return mr.stopModule(registered)
|
||||
}
|
||||
|
||||
// Pause pauses a specific module
|
||||
func (mr *ModuleRegistry) Pause(ctx context.Context, moduleID string) error {
|
||||
mr.mu.Lock()
|
||||
defer mr.mu.Unlock()
|
||||
|
||||
registered, exists := mr.modules[moduleID]
|
||||
if !exists {
|
||||
return fmt.Errorf("module not found: %s", moduleID)
|
||||
}
|
||||
|
||||
return mr.pauseModule(ctx, registered)
|
||||
}
|
||||
|
||||
// Resume resumes a paused module
|
||||
func (mr *ModuleRegistry) Resume(ctx context.Context, moduleID string) error {
|
||||
mr.mu.Lock()
|
||||
defer mr.mu.Unlock()
|
||||
|
||||
registered, exists := mr.modules[moduleID]
|
||||
if !exists {
|
||||
return fmt.Errorf("module not found: %s", moduleID)
|
||||
}
|
||||
|
||||
return mr.resumeModule(ctx, registered)
|
||||
}
|
||||
|
||||
// SetEventBus sets the event bus for the registry
|
||||
func (mr *ModuleRegistry) SetEventBus(eventBus EventBus) {
|
||||
mr.mu.Lock()
|
||||
defer mr.mu.Unlock()
|
||||
mr.eventBus = eventBus
|
||||
}
|
||||
|
||||
// SetHealthMonitor sets the health monitor for the registry
|
||||
func (mr *ModuleRegistry) SetHealthMonitor(healthMonitor HealthMonitor) {
|
||||
mr.mu.Lock()
|
||||
defer mr.mu.Unlock()
|
||||
mr.healthMonitor = healthMonitor
|
||||
}
|
||||
|
||||
// GetHealth returns the health status of all modules
|
||||
func (mr *ModuleRegistry) GetHealth() map[string]ModuleHealth {
|
||||
mr.mu.RLock()
|
||||
defer mr.mu.RUnlock()
|
||||
|
||||
health := make(map[string]ModuleHealth)
|
||||
for id, registered := range mr.modules {
|
||||
health[id] = registered.HealthStatus
|
||||
}
|
||||
|
||||
return health
|
||||
}
|
||||
|
||||
// GetMetrics returns metrics for all modules
|
||||
func (mr *ModuleRegistry) GetMetrics() map[string]ModuleMetrics {
|
||||
mr.mu.RLock()
|
||||
defer mr.mu.RUnlock()
|
||||
|
||||
metrics := make(map[string]ModuleMetrics)
|
||||
for id, registered := range mr.modules {
|
||||
metrics[id] = registered.Metrics
|
||||
}
|
||||
|
||||
return metrics
|
||||
}
|
||||
|
||||
// Shutdown gracefully shuts down the registry
|
||||
func (mr *ModuleRegistry) Shutdown(ctx context.Context) error {
|
||||
if mr.state == RegistryRunning {
|
||||
if err := mr.StopAll(ctx); err != nil {
|
||||
return fmt.Errorf("failed to stop all modules: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
mr.cancel()
|
||||
mr.state = RegistryStopped
|
||||
return nil
|
||||
}
|
||||
|
||||
// Private methods
|
||||
|
||||
func (mr *ModuleRegistry) calculateStartOrder() ([]string, error) {
|
||||
// Topological sort based on dependencies
|
||||
visited := make(map[string]bool)
|
||||
temp := make(map[string]bool)
|
||||
var order []string
|
||||
|
||||
var visit func(string) error
|
||||
visit = func(moduleID string) error {
|
||||
if temp[moduleID] {
|
||||
return fmt.Errorf("circular dependency detected involving module: %s", moduleID)
|
||||
}
|
||||
if visited[moduleID] {
|
||||
return nil
|
||||
}
|
||||
|
||||
temp[moduleID] = true
|
||||
for _, depID := range mr.dependencies[moduleID] {
|
||||
if _, exists := mr.modules[depID]; !exists {
|
||||
return fmt.Errorf("dependency not found: %s (required by %s)", depID, moduleID)
|
||||
}
|
||||
if err := visit(depID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
temp[moduleID] = false
|
||||
visited[moduleID] = true
|
||||
order = append(order, moduleID)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
for moduleID := range mr.modules {
|
||||
if !visited[moduleID] {
|
||||
if err := visit(moduleID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return order, nil
|
||||
}
|
||||
|
||||
func (mr *ModuleRegistry) initializeModule(ctx context.Context, registered *RegisteredModule) error {
|
||||
registered.State = StateInitialized
|
||||
|
||||
if err := registered.Instance.Initialize(ctx, registered.Config); err != nil {
|
||||
registered.State = StateFailed
|
||||
return err
|
||||
}
|
||||
|
||||
// Publish event
|
||||
if mr.eventBus != nil {
|
||||
mr.eventBus.Publish(ModuleEvent{
|
||||
Type: EventModuleInitialized,
|
||||
ModuleID: registered.ID,
|
||||
Timestamp: time.Now(),
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mr *ModuleRegistry) startModule(ctx context.Context, registered *RegisteredModule) error {
|
||||
if registered.State != StateInitialized && registered.State != StateStopped {
|
||||
return fmt.Errorf("invalid state for start: %s", registered.State)
|
||||
}
|
||||
|
||||
startTime := time.Now()
|
||||
registered.State = StateStarting
|
||||
registered.StartTime = startTime
|
||||
|
||||
// Create timeout context
|
||||
timeoutCtx, cancel := context.WithTimeout(ctx, registered.Config.StartTimeout)
|
||||
defer cancel()
|
||||
|
||||
if err := registered.Instance.Start(timeoutCtx); err != nil {
|
||||
registered.State = StateFailed
|
||||
return err
|
||||
}
|
||||
|
||||
registered.State = StateRunning
|
||||
registered.Metrics.StartupTime = time.Since(startTime)
|
||||
|
||||
// Start health monitoring
|
||||
if mr.healthMonitor != nil {
|
||||
mr.healthMonitor.StartMonitoring(registered)
|
||||
}
|
||||
|
||||
// Publish event
|
||||
if mr.eventBus != nil {
|
||||
mr.eventBus.Publish(ModuleEvent{
|
||||
Type: EventModuleStarted,
|
||||
ModuleID: registered.ID,
|
||||
Timestamp: time.Now(),
|
||||
Data: map[string]interface{}{
|
||||
"startup_time": registered.Metrics.StartupTime,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mr *ModuleRegistry) stopModule(registered *RegisteredModule) error {
|
||||
if registered.State != StateRunning && registered.State != StatePaused {
|
||||
return fmt.Errorf("invalid state for stop: %s", registered.State)
|
||||
}
|
||||
|
||||
stopTime := time.Now()
|
||||
registered.State = StateStopping
|
||||
|
||||
// Create timeout context
|
||||
ctx, cancel := context.WithTimeout(mr.ctx, registered.Config.StopTimeout)
|
||||
defer cancel()
|
||||
|
||||
if err := registered.Instance.Stop(ctx); err != nil {
|
||||
registered.State = StateFailed
|
||||
return err
|
||||
}
|
||||
|
||||
registered.State = StateStopped
|
||||
registered.StopTime = stopTime
|
||||
registered.Metrics.ShutdownTime = time.Since(stopTime)
|
||||
|
||||
// Stop health monitoring
|
||||
if mr.healthMonitor != nil {
|
||||
mr.healthMonitor.StopMonitoring(registered.ID)
|
||||
}
|
||||
|
||||
// Publish event
|
||||
if mr.eventBus != nil {
|
||||
mr.eventBus.Publish(ModuleEvent{
|
||||
Type: EventModuleStopped,
|
||||
ModuleID: registered.ID,
|
||||
Timestamp: time.Now(),
|
||||
Data: map[string]interface{}{
|
||||
"shutdown_time": registered.Metrics.ShutdownTime,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mr *ModuleRegistry) pauseModule(ctx context.Context, registered *RegisteredModule) error {
|
||||
if registered.State != StateRunning {
|
||||
return fmt.Errorf("invalid state for pause: %s", registered.State)
|
||||
}
|
||||
|
||||
registered.State = StatePausing
|
||||
|
||||
if err := registered.Instance.Pause(ctx); err != nil {
|
||||
registered.State = StateFailed
|
||||
return err
|
||||
}
|
||||
|
||||
registered.State = StatePaused
|
||||
|
||||
// Publish event
|
||||
if mr.eventBus != nil {
|
||||
mr.eventBus.Publish(ModuleEvent{
|
||||
Type: EventModulePaused,
|
||||
ModuleID: registered.ID,
|
||||
Timestamp: time.Now(),
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mr *ModuleRegistry) resumeModule(ctx context.Context, registered *RegisteredModule) error {
|
||||
if registered.State != StatePaused {
|
||||
return fmt.Errorf("invalid state for resume: %s", registered.State)
|
||||
}
|
||||
|
||||
registered.State = StateResuming
|
||||
|
||||
if err := registered.Instance.Resume(ctx); err != nil {
|
||||
registered.State = StateFailed
|
||||
return err
|
||||
}
|
||||
|
||||
registered.State = StateRunning
|
||||
|
||||
// Publish event
|
||||
if mr.eventBus != nil {
|
||||
mr.eventBus.Publish(ModuleEvent{
|
||||
Type: EventModuleResumed,
|
||||
ModuleID: registered.ID,
|
||||
Timestamp: time.Now(),
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mr *ModuleRegistry) startAllSequential(ctx context.Context) error {
|
||||
for _, moduleID := range mr.startOrder {
|
||||
registered := mr.modules[moduleID]
|
||||
if registered.Config.Enabled {
|
||||
if err := mr.startModule(ctx, registered); err != nil {
|
||||
mr.state = RegistryFailed
|
||||
return fmt.Errorf("failed to start module %s: %w", moduleID, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mr.state = RegistryRunning
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mr *ModuleRegistry) startAllParallel(ctx context.Context) error {
|
||||
// Start modules in parallel, respecting dependencies
|
||||
// This is a simplified implementation - in production you'd want more sophisticated parallel startup
|
||||
var wg sync.WaitGroup
|
||||
errors := make(chan error, len(mr.modules))
|
||||
|
||||
for _, moduleID := range mr.startOrder {
|
||||
registered := mr.modules[moduleID]
|
||||
if registered.Config.Enabled {
|
||||
wg.Add(1)
|
||||
go func(reg *RegisteredModule) {
|
||||
defer wg.Done()
|
||||
if err := mr.startModule(ctx, reg); err != nil {
|
||||
errors <- fmt.Errorf("failed to start module %s: %w", reg.ID, err)
|
||||
}
|
||||
}(registered)
|
||||
}
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
close(errors)
|
||||
|
||||
// Check for errors
|
||||
for err := range errors {
|
||||
mr.state = RegistryFailed
|
||||
return err
|
||||
}
|
||||
|
||||
mr.state = RegistryRunning
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mr *ModuleRegistry) stopAllSequential(ctx context.Context) error {
|
||||
for _, moduleID := range mr.stopOrder {
|
||||
registered := mr.modules[moduleID]
|
||||
if registered.State == StateRunning || registered.State == StatePaused {
|
||||
if err := mr.stopModule(registered); err != nil {
|
||||
mr.state = RegistryFailed
|
||||
return fmt.Errorf("failed to stop module %s: %w", moduleID, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mr.state = RegistryStopped
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mr *ModuleRegistry) stopAllParallel(ctx context.Context) error {
|
||||
var wg sync.WaitGroup
|
||||
errors := make(chan error, len(mr.modules))
|
||||
|
||||
for _, moduleID := range mr.stopOrder {
|
||||
registered := mr.modules[moduleID]
|
||||
if registered.State == StateRunning || registered.State == StatePaused {
|
||||
wg.Add(1)
|
||||
go func(reg *RegisteredModule) {
|
||||
defer wg.Done()
|
||||
if err := mr.stopModule(reg); err != nil {
|
||||
errors <- fmt.Errorf("failed to stop module %s: %w", reg.ID, err)
|
||||
}
|
||||
}(registered)
|
||||
}
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
close(errors)
|
||||
|
||||
// Check for errors
|
||||
for err := range errors {
|
||||
mr.state = RegistryFailed
|
||||
return err
|
||||
}
|
||||
|
||||
mr.state = RegistryStopped
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user