Complete BZZZ functionality port to CHORUS

🎭 CHORUS now contains full BZZZ functionality adapted for containers

Core systems ported:
- P2P networking (libp2p with DHT and PubSub)
- Task coordination (COOEE protocol)
- HMMM collaborative reasoning
- SHHH encryption and security
- SLURP admin election system
- UCXL content addressing
- UCXI server integration
- Hypercore logging system
- Health monitoring and graceful shutdown
- License validation with KACHING

Container adaptations:
- Environment variable configuration (no YAML files)
- Container-optimized logging to stdout/stderr
- Auto-generated agent IDs for container deployments
- Docker-first architecture

All proven BZZZ P2P protocols, AI integration, and collaboration
features are now available in containerized form.

Next: Build and test container deployment.

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
anthonyrawlins
2025-09-02 20:02:37 +10:00
parent 7c6cbd562a
commit 543ab216f9
224 changed files with 86331 additions and 186 deletions

369
pkg/shutdown/components.go Normal file
View File

@@ -0,0 +1,369 @@
package shutdown
import (
"context"
"fmt"
"net/http"
"time"
)
// HTTPServerComponent wraps an HTTP server for graceful shutdown
type HTTPServerComponent struct {
name string
server *http.Server
priority int
}
// NewHTTPServerComponent creates a new HTTP server component
func NewHTTPServerComponent(name string, server *http.Server, priority int) *HTTPServerComponent {
return &HTTPServerComponent{
name: name,
server: server,
priority: priority,
}
}
func (h *HTTPServerComponent) Name() string {
return h.name
}
func (h *HTTPServerComponent) Priority() int {
return h.priority
}
func (h *HTTPServerComponent) CanForceStop() bool {
return true
}
func (h *HTTPServerComponent) Shutdown(ctx context.Context) error {
if h.server == nil {
return nil
}
return h.server.Shutdown(ctx)
}
// P2PNodeComponent wraps a P2P node for graceful shutdown
type P2PNodeComponent struct {
name string
closer func() error
priority int
}
// NewP2PNodeComponent creates a new P2P node component
func NewP2PNodeComponent(name string, closer func() error, priority int) *P2PNodeComponent {
return &P2PNodeComponent{
name: name,
closer: closer,
priority: priority,
}
}
func (p *P2PNodeComponent) Name() string {
return p.name
}
func (p *P2PNodeComponent) Priority() int {
return p.priority
}
func (p *P2PNodeComponent) CanForceStop() bool {
return true
}
func (p *P2PNodeComponent) Shutdown(ctx context.Context) error {
if p.closer == nil {
return nil
}
// P2P nodes typically need time to disconnect gracefully
done := make(chan error, 1)
go func() {
done <- p.closer()
}()
select {
case err := <-done:
return err
case <-ctx.Done():
return ctx.Err()
}
}
// DatabaseComponent wraps a database connection for graceful shutdown
type DatabaseComponent struct {
name string
closer func() error
priority int
}
// NewDatabaseComponent creates a new database component
func NewDatabaseComponent(name string, closer func() error, priority int) *DatabaseComponent {
return &DatabaseComponent{
name: name,
closer: closer,
priority: priority,
}
}
func (d *DatabaseComponent) Name() string {
return d.name
}
func (d *DatabaseComponent) Priority() int {
return d.priority
}
func (d *DatabaseComponent) CanForceStop() bool {
return false // Databases shouldn't be force-stopped
}
func (d *DatabaseComponent) Shutdown(ctx context.Context) error {
if d.closer == nil {
return nil
}
return d.closer()
}
// ElectionManagerComponent wraps an election manager for graceful shutdown
type ElectionManagerComponent struct {
name string
stopper func()
priority int
}
// NewElectionManagerComponent creates a new election manager component
func NewElectionManagerComponent(name string, stopper func(), priority int) *ElectionManagerComponent {
return &ElectionManagerComponent{
name: name,
stopper: stopper,
priority: priority,
}
}
func (e *ElectionManagerComponent) Name() string {
return e.name
}
func (e *ElectionManagerComponent) Priority() int {
return e.priority
}
func (e *ElectionManagerComponent) CanForceStop() bool {
return true
}
func (e *ElectionManagerComponent) Shutdown(ctx context.Context) error {
if e.stopper == nil {
return nil
}
// Election managers need special handling to transfer leadership
done := make(chan struct{})
go func() {
e.stopper()
close(done)
}()
select {
case <-done:
return nil
case <-ctx.Done():
return ctx.Err()
}
}
// PubSubComponent wraps a PubSub system for graceful shutdown
type PubSubComponent struct {
name string
closer func() error
priority int
}
// NewPubSubComponent creates a new PubSub component
func NewPubSubComponent(name string, closer func() error, priority int) *PubSubComponent {
return &PubSubComponent{
name: name,
closer: closer,
priority: priority,
}
}
func (p *PubSubComponent) Name() string {
return p.name
}
func (p *PubSubComponent) Priority() int {
return p.priority
}
func (p *PubSubComponent) CanForceStop() bool {
return true
}
func (p *PubSubComponent) Shutdown(ctx context.Context) error {
if p.closer == nil {
return nil
}
return p.closer()
}
// MonitoringComponent wraps a monitoring system for graceful shutdown
type MonitoringComponent struct {
name string
closer func() error
priority int
}
// NewMonitoringComponent creates a new monitoring component
func NewMonitoringComponent(name string, closer func() error, priority int) *MonitoringComponent {
return &MonitoringComponent{
name: name,
closer: closer,
priority: priority,
}
}
func (m *MonitoringComponent) Name() string {
return m.name
}
func (m *MonitoringComponent) Priority() int {
return m.priority
}
func (m *MonitoringComponent) CanForceStop() bool {
return true
}
func (m *MonitoringComponent) Shutdown(ctx context.Context) error {
if m.closer == nil {
return nil
}
return m.closer()
}
// GenericComponent provides a generic wrapper for any component with a close function
type GenericComponent struct {
name string
closer func() error
priority int
canForceStop bool
shutdownFunc func(ctx context.Context) error
}
// NewGenericComponent creates a new generic component
func NewGenericComponent(name string, priority int, canForceStop bool) *GenericComponent {
return &GenericComponent{
name: name,
priority: priority,
canForceStop: canForceStop,
}
}
// SetCloser sets a simple closer function
func (g *GenericComponent) SetCloser(closer func() error) *GenericComponent {
g.closer = closer
return g
}
// SetShutdownFunc sets a context-aware shutdown function
func (g *GenericComponent) SetShutdownFunc(shutdownFunc func(ctx context.Context) error) *GenericComponent {
g.shutdownFunc = shutdownFunc
return g
}
func (g *GenericComponent) Name() string {
return g.name
}
func (g *GenericComponent) Priority() int {
return g.priority
}
func (g *GenericComponent) CanForceStop() bool {
return g.canForceStop
}
func (g *GenericComponent) Shutdown(ctx context.Context) error {
if g.shutdownFunc != nil {
return g.shutdownFunc(ctx)
}
if g.closer != nil {
// Wrap simple closer in context-aware function
done := make(chan error, 1)
go func() {
done <- g.closer()
}()
select {
case err := <-done:
return err
case <-ctx.Done():
return ctx.Err()
}
}
return nil
}
// WorkerPoolComponent manages a pool of workers for graceful shutdown
type WorkerPoolComponent struct {
name string
stopCh chan struct{}
workers int
priority int
shutdownTime time.Duration
}
// NewWorkerPoolComponent creates a new worker pool component
func NewWorkerPoolComponent(name string, stopCh chan struct{}, workers int, priority int) *WorkerPoolComponent {
return &WorkerPoolComponent{
name: name,
stopCh: stopCh,
workers: workers,
priority: priority,
shutdownTime: 10 * time.Second,
}
}
func (w *WorkerPoolComponent) Name() string {
return fmt.Sprintf("%s (workers: %d)", w.name, w.workers)
}
func (w *WorkerPoolComponent) Priority() int {
return w.priority
}
func (w *WorkerPoolComponent) CanForceStop() bool {
return true
}
func (w *WorkerPoolComponent) Shutdown(ctx context.Context) error {
if w.stopCh == nil {
return nil
}
// Signal workers to stop
close(w.stopCh)
// Wait for workers to finish with timeout
timeout := w.shutdownTime
if deadline, ok := ctx.Deadline(); ok {
if remaining := time.Until(deadline); remaining < timeout {
timeout = remaining
}
}
// In a real implementation, you would wait for workers to signal completion
select {
case <-time.After(timeout):
return fmt.Errorf("workers did not shut down within %v", timeout)
case <-ctx.Done():
return ctx.Err()
}
}

380
pkg/shutdown/manager.go Normal file
View File

@@ -0,0 +1,380 @@
package shutdown
import (
"context"
"fmt"
"os"
"os/signal"
"sync"
"syscall"
"time"
)
// Manager provides coordinated graceful shutdown for all system components
type Manager struct {
mu sync.RWMutex
components map[string]Component
hooks map[Phase][]Hook
timeout time.Duration
forceTimeout time.Duration
signals []os.Signal
signalCh chan os.Signal
shutdownCh chan struct{}
completedCh chan struct{}
started bool
shutdownStarted bool
logger Logger
}
// Component represents a system component that needs graceful shutdown
type Component interface {
// Name returns the component name for logging
Name() string
// Shutdown gracefully shuts down the component
Shutdown(ctx context.Context) error
// Priority returns the shutdown priority (lower numbers shut down first)
Priority() int
// CanForceStop returns true if the component can be force-stopped
CanForceStop() bool
}
// Hook represents a function to be called during shutdown phases
type Hook func(ctx context.Context) error
// Phase represents different phases of the shutdown process
type Phase int
const (
PhasePreShutdown Phase = iota // Before any components are shut down
PhaseShutdown // During component shutdown
PhasePostShutdown // After all components are shut down
PhaseCleanup // Final cleanup phase
)
// Logger interface for shutdown logging
type Logger interface {
Info(msg string, args ...interface{})
Warn(msg string, args ...interface{})
Error(msg string, args ...interface{})
}
// NewManager creates a new shutdown manager
func NewManager(timeout time.Duration, logger Logger) *Manager {
if timeout == 0 {
timeout = 30 * time.Second
}
if logger == nil {
logger = &defaultLogger{}
}
return &Manager{
components: make(map[string]Component),
hooks: make(map[Phase][]Hook),
timeout: timeout,
forceTimeout: timeout + 15*time.Second,
signals: []os.Signal{os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT},
signalCh: make(chan os.Signal, 1),
shutdownCh: make(chan struct{}),
completedCh: make(chan struct{}),
logger: logger,
}
}
// Register adds a component for graceful shutdown
func (m *Manager) Register(component Component) {
m.mu.Lock()
defer m.mu.Unlock()
if m.shutdownStarted {
m.logger.Warn("Cannot register component '%s' - shutdown already started", component.Name())
return
}
m.components[component.Name()] = component
m.logger.Info("Registered component for graceful shutdown: %s (priority: %d)",
component.Name(), component.Priority())
}
// Unregister removes a component from graceful shutdown
func (m *Manager) Unregister(name string) {
m.mu.Lock()
defer m.mu.Unlock()
if m.shutdownStarted {
m.logger.Warn("Cannot unregister component '%s' - shutdown already started", name)
return
}
delete(m.components, name)
m.logger.Info("Unregistered component from graceful shutdown: %s", name)
}
// AddHook adds a hook to be called during a specific shutdown phase
func (m *Manager) AddHook(phase Phase, hook Hook) {
m.mu.Lock()
defer m.mu.Unlock()
m.hooks[phase] = append(m.hooks[phase], hook)
}
// Start begins listening for shutdown signals
func (m *Manager) Start() {
m.mu.Lock()
if m.started {
m.mu.Unlock()
return
}
m.started = true
m.mu.Unlock()
signal.Notify(m.signalCh, m.signals...)
go m.signalHandler()
m.logger.Info("Graceful shutdown manager started, listening for signals: %v", m.signals)
}
// Stop initiates graceful shutdown programmatically
func (m *Manager) Stop() {
select {
case m.shutdownCh <- struct{}{}:
default:
// Shutdown already initiated
}
}
// Wait blocks until shutdown is complete
func (m *Manager) Wait() {
<-m.completedCh
}
// signalHandler handles OS signals and initiates shutdown
func (m *Manager) signalHandler() {
select {
case sig := <-m.signalCh:
m.logger.Info("Received signal %v, initiating graceful shutdown", sig)
m.initiateShutdown()
case <-m.shutdownCh:
m.logger.Info("Programmatic shutdown requested")
m.initiateShutdown()
}
}
// initiateShutdown performs the actual shutdown process
func (m *Manager) initiateShutdown() {
m.mu.Lock()
if m.shutdownStarted {
m.mu.Unlock()
return
}
m.shutdownStarted = true
m.mu.Unlock()
defer close(m.completedCh)
// Create main shutdown context with timeout
ctx, cancel := context.WithTimeout(context.Background(), m.timeout)
defer cancel()
// Create force shutdown context
forceCtx, forceCancel := context.WithTimeout(context.Background(), m.forceTimeout)
defer forceCancel()
// Start force shutdown monitor
go m.forceShutdownMonitor(forceCtx)
startTime := time.Now()
m.logger.Info("🛑 Beginning graceful shutdown (timeout: %v)", m.timeout)
// Phase 1: Pre-shutdown hooks
if err := m.executeHooks(ctx, PhasePreShutdown); err != nil {
m.logger.Error("Pre-shutdown hooks failed: %v", err)
}
// Phase 2: Shutdown components in priority order
if err := m.shutdownComponents(ctx); err != nil {
m.logger.Error("Component shutdown failed: %v", err)
}
// Phase 3: Post-shutdown hooks
if err := m.executeHooks(ctx, PhasePostShutdown); err != nil {
m.logger.Error("Post-shutdown hooks failed: %v", err)
}
// Phase 4: Cleanup hooks
if err := m.executeHooks(ctx, PhaseCleanup); err != nil {
m.logger.Error("Cleanup hooks failed: %v", err)
}
elapsed := time.Since(startTime)
m.logger.Info("✅ Graceful shutdown completed in %v", elapsed)
}
// executeHooks runs all hooks for a given phase
func (m *Manager) executeHooks(ctx context.Context, phase Phase) error {
m.mu.RLock()
hooks := m.hooks[phase]
m.mu.RUnlock()
if len(hooks) == 0 {
return nil
}
phaseName := map[Phase]string{
PhasePreShutdown: "pre-shutdown",
PhaseShutdown: "shutdown",
PhasePostShutdown: "post-shutdown",
PhaseCleanup: "cleanup",
}[phase]
m.logger.Info("🔧 Executing %s hooks (%d hooks)", phaseName, len(hooks))
for i, hook := range hooks {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
if err := hook(ctx); err != nil {
m.logger.Error("Hook %d in %s phase failed: %v", i+1, phaseName, err)
// Continue with other hooks even if one fails
}
}
return nil
}
// shutdownComponents shuts down all registered components in priority order
func (m *Manager) shutdownComponents(ctx context.Context) error {
m.mu.RLock()
components := make([]Component, 0, len(m.components))
for _, comp := range m.components {
components = append(components, comp)
}
m.mu.RUnlock()
if len(components) == 0 {
m.logger.Info("No components registered for shutdown")
return nil
}
// Sort components by priority (lower numbers first)
for i := 0; i < len(components)-1; i++ {
for j := i + 1; j < len(components); j++ {
if components[i].Priority() > components[j].Priority() {
components[i], components[j] = components[j], components[i]
}
}
}
m.logger.Info("🔄 Shutting down %d components in priority order", len(components))
// Shutdown components with individual timeouts
componentTimeout := m.timeout / time.Duration(len(components))
if componentTimeout < 5*time.Second {
componentTimeout = 5 * time.Second
}
for _, comp := range components {
select {
case <-ctx.Done():
m.logger.Warn("Main shutdown context cancelled, attempting force shutdown")
return m.forceShutdownRemainingComponents(components)
default:
}
compCtx, compCancel := context.WithTimeout(ctx, componentTimeout)
m.logger.Info("🔄 Shutting down component: %s (priority: %d, timeout: %v)",
comp.Name(), comp.Priority(), componentTimeout)
start := time.Now()
if err := comp.Shutdown(compCtx); err != nil {
elapsed := time.Since(start)
m.logger.Error("❌ Component '%s' shutdown failed after %v: %v",
comp.Name(), elapsed, err)
} else {
elapsed := time.Since(start)
m.logger.Info("✅ Component '%s' shutdown completed in %v",
comp.Name(), elapsed)
}
compCancel()
}
return nil
}
// forceShutdownMonitor monitors for force shutdown timeout
func (m *Manager) forceShutdownMonitor(ctx context.Context) {
<-ctx.Done()
if ctx.Err() == context.DeadlineExceeded {
m.logger.Error("💥 Force shutdown timeout reached, terminating process")
os.Exit(1)
}
}
// forceShutdownRemainingComponents attempts to force stop components that can be force-stopped
func (m *Manager) forceShutdownRemainingComponents(components []Component) error {
m.logger.Warn("🚨 Attempting force shutdown of remaining components")
for _, comp := range components {
if comp.CanForceStop() {
m.logger.Warn("🔨 Force stopping component: %s", comp.Name())
// For force stop, we give a very short timeout
forceCtx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
comp.Shutdown(forceCtx)
cancel()
} else {
m.logger.Warn("⚠️ Component '%s' cannot be force stopped", comp.Name())
}
}
return nil
}
// GetStatus returns the current shutdown status
func (m *Manager) GetStatus() *Status {
m.mu.RLock()
defer m.mu.RUnlock()
status := &Status{
Started: m.started,
ShutdownStarted: m.shutdownStarted,
ComponentCount: len(m.components),
Components: make([]string, 0, len(m.components)),
}
for name := range m.components {
status.Components = append(status.Components, name)
}
return status
}
// Status represents the current shutdown manager status
type Status struct {
Started bool `json:"started"`
ShutdownStarted bool `json:"shutdown_started"`
ComponentCount int `json:"component_count"`
Components []string `json:"components"`
}
// defaultLogger is a simple logger implementation
type defaultLogger struct{}
func (l *defaultLogger) Info(msg string, args ...interface{}) {
fmt.Printf("[INFO] "+msg+"\n", args...)
}
func (l *defaultLogger) Warn(msg string, args ...interface{}) {
fmt.Printf("[WARN] "+msg+"\n", args...)
}
func (l *defaultLogger) Error(msg string, args ...interface{}) {
fmt.Printf("[ERROR] "+msg+"\n", args...)
}