-
Notifications
You must be signed in to change notification settings - Fork 596
/
runnable_server.go
81 lines (66 loc) · 2.05 KB
/
runnable_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
/*
Copyright 2019 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package utils
import (
"context"
"net/http"
"sync"
"time"
)
// RunnableServer is a small wrapper around http.Server so that it matches the
// manager.Runnable interface.
type RunnableServer struct {
// Server is the http.Server to wrap.
*http.Server
// ServeFunc is the function used to start the http.Server. If nil,
// ListenAndServe() will be used.
ServeFunc func() error
// ShutdownTimeout is the duration to wait for the http.Server to gracefully
// shut down when the stop channel is closed. If this is zero or negative,
// the http.Server will be immediately closed instead.
ShutdownTimeout time.Duration
// WaitGroup is a temporary workaround for Manager returning immediately
// without waiting for Runnables to stop. See
// https://github.com/kubernetes-sigs/controller-runtime/issues/350.
WaitGroup *sync.WaitGroup
}
// Start the server. The server will be shut down when StopCh is closed.
func (r *RunnableServer) Start(stopCh <-chan struct{}) error {
errCh := make(chan error)
if r.WaitGroup != nil {
r.WaitGroup.Add(1)
defer r.WaitGroup.Done()
}
if r.ServeFunc == nil {
r.ServeFunc = r.Server.ListenAndServe
}
go func() {
err := r.ServeFunc()
if err != http.ErrServerClosed {
errCh <- err
}
}()
var err error
select {
case <-stopCh:
if r.ShutdownTimeout > 0 {
ctx, cancel := context.WithTimeout(context.Background(), r.ShutdownTimeout)
defer cancel()
err = r.Server.Shutdown(ctx)
} else {
err = r.Server.Close()
}
case err = <-errCh:
}
return err
}