80 lines
1.0 KiB
Go
80 lines
1.0 KiB
Go
package graceful
|
|
|
|
import (
|
|
"context"
|
|
"golang.org/x/sync/errgroup"
|
|
"log"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
)
|
|
|
|
func init() {
|
|
log.SetOutput(os.Stdout)
|
|
}
|
|
|
|
type IRunner interface {
|
|
Run(ctx context.Context) error
|
|
Stop()
|
|
}
|
|
|
|
type Graceful struct{}
|
|
|
|
type Opt func(*Graceful)
|
|
|
|
func New() *Graceful {
|
|
return &Graceful{}
|
|
}
|
|
|
|
func (g *Graceful) Run(r ...IRunner) {
|
|
eg := &errgroup.Group{}
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
for _, v := range r {
|
|
goRun(ctx, eg, v)
|
|
}
|
|
|
|
eg.Go(func() error {
|
|
ch := make(chan os.Signal, 1)
|
|
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
|
|
|
|
select {
|
|
case v := <-ch:
|
|
log.Printf("catch notfiy stop: %v", v)
|
|
}
|
|
|
|
cancel()
|
|
|
|
for _, v := range r {
|
|
v.Stop()
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
defer func() {
|
|
log.Printf("server stop")
|
|
}()
|
|
|
|
err := eg.Wait()
|
|
if err != nil {
|
|
log.Println(err)
|
|
return
|
|
}
|
|
|
|
}
|
|
|
|
func goRun(ctx context.Context, eg *errgroup.Group, r IRunner) {
|
|
eg.Go(func() error {
|
|
err := r.Run(ctx)
|
|
if err != nil {
|
|
log.Printf("run err: %s", err)
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
})
|
|
}
|