manager.go raw
1 // Package transport provides a manager for pluggable network transports.
2 package transport
3
4 import (
5 "context"
6 "fmt"
7 "sync"
8
9 "next.orly.dev/pkg/lol/log"
10
11 iface "next.orly.dev/pkg/interfaces/transport"
12 )
13
14 // Manager manages multiple transports and coordinates their lifecycle.
15 type Manager struct {
16 mu sync.RWMutex
17 transports []iface.Transport
18 }
19
20 // NewManager creates a new transport manager.
21 func NewManager() *Manager {
22 return &Manager{}
23 }
24
25 // Add registers a transport with the manager.
26 func (m *Manager) Add(t iface.Transport) {
27 m.mu.Lock()
28 defer m.mu.Unlock()
29 m.transports = append(m.transports, t)
30 }
31
32 // StartAll starts all registered transports in order.
33 // If a transport fails to start, it is logged and skipped.
34 // Returns an error only if no transports started successfully.
35 func (m *Manager) StartAll(ctx context.Context) error {
36 m.mu.RLock()
37 defer m.mu.RUnlock()
38
39 started := 0
40 for _, t := range m.transports {
41 log.I.F("starting transport: %s", t.Name())
42 if err := t.Start(ctx); err != nil {
43 log.E.F("transport %s failed to start: %v (skipping)", t.Name(), err)
44 continue
45 }
46 log.I.F("transport started: %s", t.Name())
47 started++
48 }
49 if started == 0 {
50 return fmt.Errorf("no transports started successfully")
51 }
52 return nil
53 }
54
55 // StopAll stops all transports in reverse order.
56 func (m *Manager) StopAll(ctx context.Context) error {
57 m.mu.RLock()
58 defer m.mu.RUnlock()
59
60 var firstErr error
61 for i := len(m.transports) - 1; i >= 0; i-- {
62 t := m.transports[i]
63 log.I.F("stopping transport: %s", t.Name())
64 if err := t.Stop(ctx); err != nil {
65 log.E.F("failed to stop transport %s: %v", t.Name(), err)
66 if firstErr == nil {
67 firstErr = err
68 }
69 } else {
70 log.I.F("transport stopped: %s", t.Name())
71 }
72 }
73 return firstErr
74 }
75
76 // Addresses returns all addresses from all transports.
77 func (m *Manager) Addresses() []string {
78 m.mu.RLock()
79 defer m.mu.RUnlock()
80
81 var addrs []string
82 for _, t := range m.transports {
83 addrs = append(addrs, t.Addresses()...)
84 }
85 return addrs
86 }
87