-
Notifications
You must be signed in to change notification settings - Fork 5
/
service.go
148 lines (125 loc) · 3.11 KB
/
service.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
139
140
141
142
143
144
145
146
147
148
package rocketmq
import (
"errors"
"fmt"
"sync/atomic"
)
var errNotRunning = errors.New("server not running")
// State job state
type State int32
// Set update value atomic
func (s *State) Set(o, n State) bool {
return atomic.CompareAndSwapInt32((*int32)(s), int32(o), int32(n))
}
// Get get the value atomic
func (s *State) Get() State {
return State(atomic.LoadInt32((*int32)(s)))
}
func (s State) String() string {
switch s {
case StateCreating:
return "Createing"
case StateRunning:
return "Running"
case StateStopped:
return "Stopped"
case StateStartFailed:
return "StartFailed"
default:
panic(fmt.Sprintf("BUG:unknow state:%d", s))
}
}
const (
// StateCreating job is creating
StateCreating State = iota
// StateRunning job is running
StateRunning
// StateStopped job is stopped
StateStopped
// StateStartFailed job starts failed
StateStartFailed
)
// Shutdowner shutdown interface
type Shutdowner interface {
Shutdown()
}
// ShutdownFunc shutdown func
type ShutdownFunc func()
// Shutdown call shutdown func
func (f ShutdownFunc) Shutdown() {
f()
}
// ShutdownCollection shutdowner collection
type ShutdownCollection struct {
shutdowns []Shutdowner
}
// AddLastFuncs add shutdown funcs
func (c *ShutdownCollection) AddLastFuncs(fs ...func()) {
for _, f := range fs {
c.shutdowns = append(c.shutdowns, ShutdownFunc(f))
}
}
// AddLast append shutdowne funcs to the end
func (c *ShutdownCollection) AddLast(s ...Shutdowner) {
c.shutdowns = append(c.shutdowns, s...)
}
// AddFirstFuncs insert the shutdowner at the beginning
func (c *ShutdownCollection) AddFirstFuncs(fs ...func()) {
s := make([]Shutdowner, len(fs))
for i, f := range fs {
s[i] = ShutdownFunc(f)
}
c.AddFirst(s...)
}
// AddFirst insert the shutdowner at the beginning
func (c *ShutdownCollection) AddFirst(s ...Shutdowner) {
l := len(s)
r := make([]Shutdowner, len(c.shutdowns)+l)
copy(r, s)
copy(r[l:], c.shutdowns)
c.shutdowns = r
}
// Shutdown call all the added shutdown func, in the added order
func (c *ShutdownCollection) Shutdown() {
for _, shutdown := range c.shutdowns {
shutdown.Shutdown()
}
}
// Server server with start&shutdown operation
type Server struct {
State State
StartFunc func() error
Shutdowner Shutdowner
}
// Start starts server
// it checks the state, if current is not StateCreating, returns started failed error
func (s *Server) Start() error {
if s.StartFunc == nil {
return errors.New("empty start func")
}
if !s.State.Set(StateCreating, StateStartFailed) {
return fmt.Errorf("Start failed, since current state is:%s", s.State.Get())
}
if err := s.StartFunc(); err != nil {
return err
}
s.State.Set(StateStartFailed, StateRunning)
return nil
}
// CheckRunning check the server is under running state, return false if not
func (s *Server) CheckRunning() error {
if s.State.Get() != StateRunning {
return errNotRunning
}
return nil
}
// Shutdown shutdown server
// it checks the state,if current state is not StateRunning return false
func (s *Server) Shutdown() {
if !s.State.Set(StateRunning, StateStopped) {
return
}
if s.Shutdowner != nil {
s.Shutdowner.Shutdown()
}
}