zquit.go 1.53 KB
Newer Older
Vladimir Barsukov's avatar
Vladimir Barsukov committed
1
2
3
package zquit

import (
Vladimir Barsukov's avatar
zgo    
Vladimir Barsukov committed
4
	"git.barsukov.pro/barsukov/zgo/zwg"
Vladimir Barsukov's avatar
Vladimir Barsukov committed
5
	"github.com/gin-gonic/gin"
Vladimir Barsukov's avatar
Vladimir Barsukov committed
6
	"log"
Vladimir Barsukov's avatar
Vladimir Barsukov committed
7
8
9
10
	"net/http"
	"os"
	"os/signal"
	"syscall"
Vladimir Barsukov's avatar
Vladimir Barsukov committed
11
	"time"
Vladimir Barsukov's avatar
Vladimir Barsukov committed
12
13
14
)

type ZQuit struct {
Vladimir Barsukov's avatar
Vladimir Barsukov committed
15
16
17
	Name        string
	PostWaitDur time.Duration

Vladimir Barsukov's avatar
Vladimir Barsukov committed
18
	isQuit bool
Vladimir Barsukov's avatar
zgo    
Vladimir Barsukov committed
19
	wg     *zwg.Zwg
Vladimir Barsukov's avatar
Vladimir Barsukov committed
20
21
}

Vladimir Barsukov's avatar
Vladimir Barsukov committed
22
func New(name string, postWaitDur time.Duration) *ZQuit {
Vladimir Barsukov's avatar
zgo    
Vladimir Barsukov committed
23
	return &ZQuit{
Vladimir Barsukov's avatar
Vladimir Barsukov committed
24
25
26
27
28
29
30
31
32
		Name:        name,
		PostWaitDur: postWaitDur,
		wg:          zwg.New(),
	}
}

func Default(name ...string) *ZQuit {
	if len(name) == 0 {
		name = []string{"MAIN"}
Vladimir Barsukov's avatar
zgo    
Vladimir Barsukov committed
33
	}
Vladimir Barsukov's avatar
Vladimir Barsukov committed
34
35

	return New(name[0], time.Second)
Vladimir Barsukov's avatar
Vladimir Barsukov committed
36
37
38
}

func (q *ZQuit) Inc() {
Vladimir Barsukov's avatar
zgo    
Vladimir Barsukov committed
39
	q.wg.Inc()
Vladimir Barsukov's avatar
Vladimir Barsukov committed
40
41
42
43
44
45
46
}

func (q *ZQuit) Done() {
	q.wg.Done()
}

func (q *ZQuit) Wait() {
Vladimir Barsukov's avatar
fix    
Vladimir Barsukov committed
47
48
	q.Shutdown()

Vladimir Barsukov's avatar
Vladimir Barsukov committed
49
50
51
52
	q.wg.Wait()
}

func (q *ZQuit) IncDefer() func() {
Vladimir Barsukov's avatar
zgo    
Vladimir Barsukov committed
53
	return q.wg.IncDefer()
Vladimir Barsukov's avatar
Vladimir Barsukov committed
54
55
56
57
58
59
}

func (q *ZQuit) IsQuit() bool {
	return q.isQuit
}

Vladimir Barsukov's avatar
zgo    
Vladimir Barsukov committed
60
61
func (q *ZQuit) Val() int {
	return q.wg.Val()
Vladimir Barsukov's avatar
Vladimir Barsukov committed
62
63
64
65
66
67
68
}

func (q *ZQuit) WaitInterruptPrePost(pre func(), post func()) {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	<-c

Vladimir Barsukov's avatar
Vladimir Barsukov committed
69
70
71
72
	if pre != nil {
		pre()
	}

Vladimir Barsukov's avatar
Vladimir Barsukov committed
73
	q.Wait()
Vladimir Barsukov's avatar
Vladimir Barsukov committed
74
	time.Sleep(q.PostWaitDur)
Vladimir Barsukov's avatar
Vladimir Barsukov committed
75

Vladimir Barsukov's avatar
fix    
Vladimir Barsukov committed
76
77
78
	if post != nil {
		post()
	}
Vladimir Barsukov's avatar
Vladimir Barsukov committed
79
80
81
}

func (q *ZQuit) WaitInterrupt() {
Vladimir Barsukov's avatar
fix    
Vladimir Barsukov committed
82
	q.WaitInterruptPrePost(nil, nil)
Vladimir Barsukov's avatar
Vladimir Barsukov committed
83
84
}

Vladimir Barsukov's avatar
zgo    
Vladimir Barsukov committed
85
func (q *ZQuit) Middleware(c *gin.Context) {
Vladimir Barsukov's avatar
Vladimir Barsukov committed
86
87
	if q.isQuit {
		c.Data(http.StatusServiceUnavailable, "text/plain", []byte("server shutdown"))
Vladimir Barsukov's avatar
Vladimir Barsukov committed
88
		c.Abort()
Vladimir Barsukov's avatar
Vladimir Barsukov committed
89
90
91
92
93
94
95
96
		return
	}

	cancel := q.IncDefer()
	defer cancel()

	c.Next()
}
Vladimir Barsukov's avatar
zgo    
Vladimir Barsukov committed
97

Vladimir Barsukov's avatar
Vladimir Barsukov committed
98
99
100
101
102
103
104
105
106
func (q *ZQuit) PrintStat() {
	go func() {
		for {
			<-time.After(time.Second)
			log.Printf("Z_QUIT: LOCKS[%s]: %v", q.Name, q.Val())
		}
	}()
}

Vladimir Barsukov's avatar
zgo    
Vladimir Barsukov committed
107
108
109
func (q *ZQuit) Shutdown() {
	q.isQuit = true
}