@@ -11,6 +11,11 @@ import (
11
11
12
12
// SimpleComponent is the struct that implements the Component interface.
13
13
type SimpleComponent struct {
14
+ // stateChangeFuncs
15
+ stateChangeFuncs []func (prevState , newState ComponentState )
16
+ //mutex
17
+ mutex sync.RWMutex
18
+ // CompId is the unique identifier for the component.
14
19
CompId string
15
20
// AfterStart is the function that will be called after the component is started
16
21
// The function will be called with the error returned by the StartFunc.
@@ -24,8 +29,6 @@ type SimpleComponent struct {
24
29
BeforeStop func ()
25
30
// CompState is the current state of the component.
26
31
CompState ComponentState
27
- // OnStateChange is the function that will be called when the component state changes.
28
- OnStateChange func (prevState , newState ComponentState )
29
32
//StartFunc is the function that will be called when the component is started.
30
33
// It returns an error if the component failed to start.
31
34
StartFunc func () error
@@ -34,15 +37,13 @@ type SimpleComponent struct {
34
37
StopFunc func () error
35
38
}
36
39
37
- // ComponentId is the unique identifier for the component.
38
- func (sc * SimpleComponent ) Id () string {
39
- return sc .CompId
40
- }
41
-
42
- // OnChange is the function that will be called when the component state changes.
43
- func (sc * SimpleComponent ) OnChange (prevState , newState ComponentState ) {
44
- if sc .OnStateChange != nil {
45
- sc .OnStateChange (prevState , newState )
40
+ // handleStateChange is the function that will be called when the component state changes.
41
+ func (sc * SimpleComponent ) handleStateChange (prevState , newState ComponentState ) {
42
+ // if sc.OnStateChange != nil {
43
+ // sc.OnStateChange(prevState, newState)
44
+ // }
45
+ for _ , f := range sc .stateChangeFuncs {
46
+ f (prevState , newState )
46
47
}
47
48
if newState == Starting && sc .BeforeStart != nil {
48
49
sc .BeforeStart ()
@@ -51,10 +52,22 @@ func (sc *SimpleComponent) OnChange(prevState, newState ComponentState) {
51
52
}
52
53
}
53
54
55
+ // ComponentId is the unique identifier for the component.
56
+ func (sc * SimpleComponent ) Id () string {
57
+ return sc .CompId
58
+ }
59
+
60
+ // OnChange is the function that will be called when the component state changes.
61
+ func (sc * SimpleComponent ) OnChange (f func (prevState , newState ComponentState )) {
62
+ sc .mutex .Lock ()
63
+ defer sc .mutex .Unlock ()
64
+ sc .stateChangeFuncs = append (sc .stateChangeFuncs , f )
65
+ }
66
+
54
67
// Start will starting the LifeCycle.
55
68
func (sc * SimpleComponent ) Start () (err error ) {
56
69
if sc .StartFunc != nil {
57
- sc .OnChange (sc .CompState , Starting )
70
+ sc .handleStateChange (sc .CompState , Starting )
58
71
sc .CompState = Starting
59
72
err = sc .StartFunc ()
60
73
if err != nil {
@@ -63,9 +76,7 @@ func (sc *SimpleComponent) Start() (err error) {
63
76
sc .CompState = Running
64
77
65
78
}
66
- if sc .OnStateChange != nil {
67
- sc .OnStateChange (Starting , sc .CompState )
68
- }
79
+ sc .handleStateChange (Starting , sc .CompState )
69
80
if sc .AfterStart != nil {
70
81
sc .AfterStart (err )
71
82
}
@@ -77,17 +88,15 @@ func (sc *SimpleComponent) Start() (err error) {
77
88
// Stop will stop the LifeCycle.
78
89
func (sc * SimpleComponent ) Stop () (err error ) {
79
90
if sc .StopFunc != nil {
80
- sc .OnChange (sc .CompState , Stopping )
91
+ sc .handleStateChange (sc .CompState , Stopping )
81
92
sc .CompState = Stopping
82
93
err = sc .StopFunc ()
83
94
if err != nil {
84
95
sc .CompState = Error
85
96
} else {
86
97
sc .CompState = Stopped
87
98
}
88
- if sc .OnStateChange != nil {
89
- sc .OnStateChange (Stopping , sc .CompState )
90
- }
99
+ sc .handleStateChange (Stopping , sc .CompState )
91
100
if sc .AfterStop != nil {
92
101
sc .AfterStop (err )
93
102
@@ -104,9 +113,10 @@ func (sc *SimpleComponent) State() ComponentState {
104
113
105
114
// SimpleComponentManager is the struct that manages the component.
106
115
type SimpleComponentManager struct {
107
- components map [string ]Component
108
- cMutex * sync.RWMutex
109
- waitChan chan struct {}
116
+ components map [string ]Component
117
+ componentIds []string
118
+ cMutex * sync.RWMutex
119
+ waitChan chan struct {}
110
120
}
111
121
112
122
// GetState will return the current state of the LifeCycle for the component with the given id.
@@ -126,12 +136,22 @@ func (scm *SimpleComponentManager) List() []Component {
126
136
defer scm .cMutex .RUnlock ()
127
137
// Create a slice of Component and iterate over the components map and append the components to the slice.
128
138
components := make ([]Component , 0 , len (scm .components ))
129
- for _ , component := range scm .components {
130
- components = append (components , component )
139
+ for _ , compId := range scm .componentIds {
140
+ components = append (components , scm . components [ compId ] )
131
141
}
132
142
return components
133
143
}
134
144
145
+ // OnChange is the function that will be called when the component state changes.
146
+ func (scm * SimpleComponentManager ) OnChange (id string , f func (prevState , newState ComponentState )) {
147
+ scm .cMutex .Lock ()
148
+ defer scm .cMutex .Unlock ()
149
+ component , exists := scm .components [id ]
150
+ if exists {
151
+ component .OnChange (f )
152
+ }
153
+ }
154
+
135
155
// Register will register a new Components.
136
156
// if the component is already registered, get the old component.
137
157
func (scm * SimpleComponentManager ) Register (component Component ) Component {
@@ -141,33 +161,11 @@ func (scm *SimpleComponentManager) Register(component Component) Component {
141
161
oldComponent , exists := scm .components [component .Id ()]
142
162
if ! exists {
143
163
scm .components [component .Id ()] = component
164
+ scm .componentIds = append (scm .componentIds , component .Id ())
144
165
}
145
166
return oldComponent
146
167
}
147
168
148
- // StartAll will start all the Components. Returns the number of components started
149
- func (scm * SimpleComponentManager ) StartAll () error {
150
- var err * errutils.MultiError = errutils .NewMultiErr (nil )
151
- for id := range scm .components {
152
- e := scm .Start (id )
153
- if e != nil {
154
- err .Add (e )
155
- }
156
- }
157
- if err .HasErrors () {
158
- return err
159
- } else {
160
- return nil
161
- }
162
- }
163
-
164
- // StartAndWait will start all the Components. And will wait for them to be stopped.
165
- func (scm * SimpleComponentManager ) StartAndWait () {
166
- scm .StartAll () // Start all the components
167
- scm .Wait () // Wait for all the components to finish
168
-
169
- }
170
-
171
169
// Start will start the LifeCycle for the component with the given id. It returns if the component was started.
172
170
func (scm * SimpleComponentManager ) Start (id string ) (err error ) {
173
171
scm .cMutex .Lock ()
@@ -190,14 +188,38 @@ func (scm *SimpleComponentManager) Start(id string) (err error) {
190
188
return ErrCompNotFound
191
189
}
192
190
191
+ // StartAll will start all the Components. Returns the number of components started
192
+ func (scm * SimpleComponentManager ) StartAll () error {
193
+ var err * errutils.MultiError = errutils .NewMultiErr (nil )
194
+ for _ , id := range scm .componentIds {
195
+ e := scm .Start (id )
196
+ if e != nil {
197
+ err .Add (e )
198
+ }
199
+ }
200
+ if err .HasErrors () {
201
+ return err
202
+ } else {
203
+ return nil
204
+ }
205
+ }
206
+
207
+ // StartAndWait will start all the Components. And will wait for them to be stopped.
208
+ func (scm * SimpleComponentManager ) StartAndWait () {
209
+ scm .StartAll () // Start all the components
210
+ scm .Wait () // Wait for all the components to finish
211
+
212
+ }
213
+
193
214
// StopAll will stop all the Components.
194
215
func (scm * SimpleComponentManager ) StopAll () error {
195
216
logger .InfoF ("Stopping all components" )
196
217
err := errutils .NewMultiErr (nil )
197
218
scm .cMutex .Lock ()
198
219
defer scm .cMutex .Unlock ()
199
220
wg := & sync.WaitGroup {}
200
- for _ , component := range scm .components {
221
+ for i := len (scm .componentIds ) - 1 ; i >= 0 ; i -- {
222
+ component := scm.components [scm.componentIds [i ]]
201
223
if component .State () == Running {
202
224
wg .Add (1 )
203
225
go func (c Component , wg * sync.WaitGroup ) {
@@ -257,18 +279,24 @@ func (scm *SimpleComponentManager) Unregister(id string) {
257
279
component .Stop ()
258
280
}
259
281
delete (scm .components , id )
282
+ for i , compId := range scm .componentIds {
283
+ if compId == id {
284
+ scm .componentIds = append (scm .componentIds [:i ], scm .componentIds [i + 1 :]... )
285
+ break
286
+ }
287
+ }
260
288
}
261
289
}
262
290
263
291
// Wait will wait for all the Components to finish.
264
292
func (scm * SimpleComponentManager ) Wait () {
265
- go func () {
266
- // Wait for a signal to stop the components.
267
- signalChan := make (chan os.Signal , 1 )
268
- signal .Notify (signalChan , syscall .SIGTERM , syscall .SIGINT )
269
- <- signalChan
270
- scm .StopAll ()
271
- }()
293
+ // go func() {
294
+ // // Wait for a signal to stop the components.
295
+ // signalChan := make(chan os.Signal, 1)
296
+ // signal.Notify(signalChan, syscall.SIGTERM, syscall.SIGINT)
297
+ // <-signalChan
298
+ // scm.StopAll()
299
+ // }()
272
300
<- scm .waitChan
273
301
274
302
}
0 commit comments