-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.go
106 lines (88 loc) · 2.28 KB
/
server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package servers
import (
"time"
"github.com/bweston92/healthz/healthz"
)
type (
Server struct {
// addr to bind the internal HTTP server which has /healthz and /metrics endpoints.
addr string
// transports are all the servers we will be handling.
transports []transportStateManager
// healthz configuration
healthz *healthz.Healthz
}
serverOptions struct {
addr string
transports []transportStateManager
healthzComponents []*healthz.Component
healthzMeta healthz.Meta
}
transportStateManager interface {
Start() <-chan error
Stop() error
}
Option func(*serverOptions) error
)
func New(opts ...Option) (*Server, error) {
config := &serverOptions{
addr: ":8001",
transports: []transportStateManager{},
healthzComponents: []*healthz.Component{},
healthzMeta: healthz.Meta{},
}
for _, o := range opts {
if err := o(config); err != nil {
return nil, err
}
}
return &Server{
addr: config.addr,
transports: config.transports,
healthz: healthz.New(config.healthzMeta, config.healthzComponents...),
}, nil
}
// Run will start the internal HTTP server for health and metrics
// along with other transports that is registered on the transports
// member.
// When a transport gives an error back we will Close all the other
// transports and send the error to the channel returned.
func (s *Server) Run() <-chan error {
errC := make(chan error)
total := len(s.transports)
internalErrorOffset := total
transportErrs := make([]<-chan error, internalErrorOffset+1)
for i := 0; i < internalErrorOffset; i++ {
transportErrs[i] = make(chan error)
}
transportErrs[internalErrorOffset] = s.runInternalHTTP()
for offset, transport := range s.transports {
transportErrs[offset] = transport.Start()
}
s.healthz.Started()
go func() {
var transportErr error
died := -1
for died == -1 {
for offset, transportErrC := range transportErrs {
select {
case err := <-transportErrC:
transportErr = err
died = offset
goto closeServers
default:
}
}
time.Sleep(1 * time.Second)
}
closeServers:
for offset, transport := range s.transports {
if offset == died {
continue
}
transport.Stop()
}
errC <- transportErr
}()
return (<-chan error)(errC)
}