You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
86 lines
2.1 KiB
86 lines
2.1 KiB
// Package transport provides a manager for pluggable network transports. |
|
package transport |
|
|
|
import ( |
|
"context" |
|
"fmt" |
|
"sync" |
|
|
|
"lol.mleku.dev/log" |
|
|
|
iface "next.orly.dev/pkg/interfaces/transport" |
|
) |
|
|
|
// Manager manages multiple transports and coordinates their lifecycle. |
|
type Manager struct { |
|
mu sync.RWMutex |
|
transports []iface.Transport |
|
} |
|
|
|
// NewManager creates a new transport manager. |
|
func NewManager() *Manager { |
|
return &Manager{} |
|
} |
|
|
|
// Add registers a transport with the manager. |
|
func (m *Manager) Add(t iface.Transport) { |
|
m.mu.Lock() |
|
defer m.mu.Unlock() |
|
m.transports = append(m.transports, t) |
|
} |
|
|
|
// StartAll starts all registered transports in order. |
|
// If any transport fails to start, previously started transports are stopped. |
|
func (m *Manager) StartAll(ctx context.Context) error { |
|
m.mu.RLock() |
|
defer m.mu.RUnlock() |
|
|
|
for i, t := range m.transports { |
|
log.I.F("starting transport: %s", t.Name()) |
|
if err := t.Start(ctx); err != nil { |
|
// Stop previously started transports in reverse order |
|
for j := i - 1; j >= 0; j-- { |
|
if stopErr := m.transports[j].Stop(ctx); stopErr != nil { |
|
log.E.F("failed to stop transport %s during rollback: %v", |
|
m.transports[j].Name(), stopErr) |
|
} |
|
} |
|
return fmt.Errorf("transport %s failed to start: %w", t.Name(), err) |
|
} |
|
log.I.F("transport started: %s", t.Name()) |
|
} |
|
return nil |
|
} |
|
|
|
// StopAll stops all transports in reverse order. |
|
func (m *Manager) StopAll(ctx context.Context) error { |
|
m.mu.RLock() |
|
defer m.mu.RUnlock() |
|
|
|
var firstErr error |
|
for i := len(m.transports) - 1; i >= 0; i-- { |
|
t := m.transports[i] |
|
log.I.F("stopping transport: %s", t.Name()) |
|
if err := t.Stop(ctx); err != nil { |
|
log.E.F("failed to stop transport %s: %v", t.Name(), err) |
|
if firstErr == nil { |
|
firstErr = err |
|
} |
|
} else { |
|
log.I.F("transport stopped: %s", t.Name()) |
|
} |
|
} |
|
return firstErr |
|
} |
|
|
|
// Addresses returns all addresses from all transports. |
|
func (m *Manager) Addresses() []string { |
|
m.mu.RLock() |
|
defer m.mu.RUnlock() |
|
|
|
var addrs []string |
|
for _, t := range m.transports { |
|
addrs = append(addrs, t.Addresses()...) |
|
} |
|
return addrs |
|
}
|
|
|