-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.go
104 lines (89 loc) · 1.67 KB
/
app.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
package gap
import (
"context"
"errors"
"os"
"os/signal"
"sync"
"syscall"
logx "github.com/hzhhong/gap/log"
"golang.org/x/sync/errgroup"
)
type options struct {
ctx context.Context
servers []*Server
logger logx.Logger
}
type Option func(*options)
type App struct {
opts options
ctx context.Context
cancel func()
}
// New App
func NewApp(opts ...Option) *App {
options := options{
ctx: context.Background(),
logger: logx.DefaultLogger,
}
for _, o := range opts {
o(&options)
}
ctx, cancel := context.WithCancel(options.ctx)
return &App{
ctx: ctx,
cancel: cancel,
opts: options,
}
}
// Servers 添加Server
func Servers(srv ...*Server) Option {
return func(o *options) { o.servers = srv }
}
// Servers 添加logger
func Logger(logger logx.Logger) Option {
return func(o *options) { o.logger = logger }
}
// Stop gracefully stops the application.
func (a *App) Stop() error {
//todo
if a.cancel != nil {
a.cancel()
}
return nil
}
func (app *App) Run() error {
ctx, cancel := context.WithCancel(app.ctx)
defer cancel()
eg, ctx := errgroup.WithContext(ctx)
wg := sync.WaitGroup{}
for _, srv := range app.opts.servers {
srv := srv
eg.Go(func() error {
<-ctx.Done() // wait for stop signal
return srv.Stop(ctx)
})
wg.Add(1)
eg.Go(func() error {
wg.Done()
return srv.Start()
})
}
wg.Wait()
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
eg.Go(func() error {
for {
select {
case <-ctx.Done():
return ctx.Err()
case <-c:
app.Stop()
}
}
})
if err := eg.Wait(); err != nil && !errors.Is(err, context.Canceled) {
return err
}
return nil
}