-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexample_test.go
More file actions
115 lines (101 loc) · 3.3 KB
/
example_test.go
File metadata and controls
115 lines (101 loc) · 3.3 KB
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
107
108
109
110
111
112
113
114
115
package svcinit_test
import (
"context"
"errors"
"fmt"
"net"
"net/http"
"os"
"syscall"
"time"
"github.com/rrgmc/svcinit/v3"
)
// healthService implements an HTTP server used to serve health probes.
type healthService struct {
server *http.Server
}
func newHealthService() *healthService {
return &healthService{
server: &http.Server{
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}),
Addr: ":8081",
},
}
}
func (s *healthService) Start(ctx context.Context) error {
s.server.BaseContext = func(net.Listener) context.Context {
return ctx
}
return s.server.ListenAndServe()
}
func (s *healthService) Stop(ctx context.Context) error {
return s.server.Shutdown(ctx)
}
func ExampleManager() {
ctx := context.Background()
sinit, err := svcinit.New(
// initialization in 3 stages. Initialization is done in stage order, and shutdown in reverse stage order.
// all tasks added to the same stage are started/stopped in parallel.
svcinit.WithStages(svcinit.StageDefault, "manage", "service"),
// use a context with a 20-second cancellation during shutdown.
svcinit.WithShutdownTimeout(20*time.Second),
// some tasks may not check context cancellation, set enforce to true to give up waiting after the shutdown timeout.
// The default is true.
svcinit.WithEnforceShutdownTimeout(true),
)
if err != nil {
fmt.Println(err)
return
}
// add a task to start health HTTP server before the service, and stop it after.
sinit.AddTask("manage", svcinit.BuildDataTask[*healthService](
// the "BuildDataTask" setup callback returns an instance that is sent to all following steps.
func(ctx context.Context) (*healthService, error) {
return newHealthService(), nil
},
svcinit.WithDataStart(func(ctx context.Context, service *healthService) error {
return service.Start(ctx)
}),
svcinit.WithDataStop(func(ctx context.Context, service *healthService) error {
return service.Stop(ctx)
}),
))
// add a task to start the core HTTP server.
sinit.AddTask("service", svcinit.BuildDataTask[*http.Server](
func(ctx context.Context) (*http.Server, error) {
// initialize the service in the setup step.
// as this may take some time in bigger services, initializing here allows other tasks to initialize
// at the same time.
server := &http.Server{
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}),
Addr: ":8080",
}
return server, nil
},
svcinit.WithDataStart(func(ctx context.Context, service *http.Server) error {
service.BaseContext = func(net.Listener) context.Context {
return ctx
}
return service.ListenAndServe()
}),
// stop the service. By default, the context is NOT cancelled, this method must arrange for the start
// function to end.
svcinit.WithDataStop(func(ctx context.Context, service *http.Server) error {
return service.Shutdown(ctx)
}),
))
// shutdown on OS signal.
sinit.AddTask(svcinit.StageDefault, svcinit.SignalTask(os.Interrupt, syscall.SIGTERM))
// sleep 100ms and shutdown.
sinit.AddTask(svcinit.StageDefault, svcinit.TimeoutTask(100*time.Millisecond,
svcinit.WithTimeoutTaskError(errors.New("timed out"))))
err = sinit.Run(ctx)
if err != nil {
fmt.Println("err:", err)
}
// Output: err: timed out
}