-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp.go
138 lines (108 loc) · 2.53 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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package gofr
import (
"context"
"os"
"sync"
"syscall"
"time"
"github.com/google/uuid"
"github.com/pkg/errors"
"golang.org/x/sync/errgroup"
"github.com/neo532/gofr/logger"
"github.com/neo532/gofr/logger/log"
)
// IApp is application context value.
type IApp interface {
ID() string
Name() string
Version() string
Metadata() map[string]string
Endpoint() []string
}
type App struct {
opts *options
cancel func()
}
func New(opts ...Option) (a *App) {
a = &App{
opts: &options{
sigs: []os.Signal{syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT},
stopTimeout: 10 * time.Second,
logger: logger.NewDefaultLogger(log.New()),
ctx: context.Background(),
},
}
for _, opt := range opts {
opt(a.opts)
}
a.opts.ctx, a.cancel = context.WithCancel(a.opts.ctx)
if a.opts.id == "" {
if id, err := uuid.NewUUID(); err == nil {
a.opts.id = id.String()
}
}
return
}
// ID returns app instance id.
func (a *App) ID() string { return a.opts.id }
// Name returns service name.
func (a *App) Name() string { return a.opts.name }
// Version returns app version.
func (a *App) Version() string { return a.opts.version }
// Metadata returns service metadata.
func (a *App) Metadata() map[string]string { return a.opts.metadata }
// Endpoint returns endpoints.
func (a *App) Endpoint() []string { return a.opts.endpoints }
func (a *App) Run() (err error) {
for _, fn := range a.opts.beforeStart {
if err = fn(a.opts.ctx); err != nil {
return
}
}
eg, _ := errgroup.WithContext(a.opts.ctx)
wg := sync.WaitGroup{}
for _, srv := range a.opts.servers {
eg.Go(func() error {
return srv.Start(a.opts.ctx)
})
}
wg.Wait()
for _, fn := range a.opts.afterStart {
if err = fn(a.opts.ctx); err != nil {
return
}
}
return
}
func (a *App) Stop() (err error) {
for _, fn := range a.opts.beforeStop {
if er := fn(a.opts.ctx); er != nil {
err = WrapErr(err, er)
}
}
if a.cancel != nil {
a.cancel()
}
for _, fn := range a.opts.afterStop {
if er := fn(a.opts.ctx); er != nil {
err = WrapErr(err, er)
}
}
return
}
type iAppKey struct{}
// NewContext returns a new Context that carries value.
func NewContext(ctx context.Context, a IApp) context.Context {
return context.WithValue(ctx, iAppKey{}, a)
}
// FromContext returns the Transport value stored in ctx, if any.
func FromContext(ctx context.Context) (a IApp, ok bool) {
a, ok = ctx.Value(iAppKey{}).(IApp)
return
}
func WrapErr(err error, er error) error {
if err != nil {
return errors.Wrap(err, er.Error())
}
return er
}