Skip to content

Commit df36c41

Browse files
committed
Revise Process lifecycle state machine
- removed StateFailed - StateStarting --> StartStopped is OK - updated tests
1 parent 8f68dd6 commit df36c41

File tree

3 files changed

+15
-29
lines changed

3 files changed

+15
-29
lines changed

proxy/process.go

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@ const (
2424
StateReady ProcessState = ProcessState("ready")
2525
StateStopping ProcessState = ProcessState("stopping")
2626

27-
// failed a health check on start and will not be recovered
28-
StateFailed ProcessState = ProcessState("failed")
29-
3027
// process is shutdown and will not be restarted
3128
StateShutdown ProcessState = ProcessState("shutdown")
3229
)
@@ -70,6 +67,9 @@ type Process struct {
7067

7168
// used for testing to override the default value
7269
gracefulStopTimeout time.Duration
70+
71+
// track the number of failed starts
72+
failedStartCount int
7373
}
7474

7575
func NewProcess(ID string, healthCheckTimeout int, config ModelConfig, processLogger *LogMonitor, proxyLogger *LogMonitor) *Process {
@@ -137,13 +137,11 @@ func isValidTransition(from, to ProcessState) bool {
137137
case StateStopped:
138138
return to == StateStarting
139139
case StateStarting:
140-
return to == StateReady || to == StateFailed || to == StateStopping
140+
return to == StateReady || to == StateStopping || to == StateStopped
141141
case StateReady:
142142
return to == StateStopping
143143
case StateStopping:
144144
return to == StateStopped || to == StateShutdown
145-
case StateFailed:
146-
return to == StateStopping
147145
case StateShutdown:
148146
return false // No transitions allowed from these states
149147
}
@@ -202,11 +200,13 @@ func (p *Process) start() error {
202200
p.cancelUpstream = ctxCancelUpstream
203201
p.cmdWaitChan = make(chan struct{})
204202

203+
p.failedStartCount++ // this will be reset to zero when the process has successfully started
205204
err = p.cmd.Start()
206205

207206
// Set process state to failed
208207
if err != nil {
209-
if curState, swapErr := p.swapState(StateStarting, StateFailed); swapErr != nil {
208+
if curState, swapErr := p.swapState(StateStarting, StateStopped); swapErr != nil {
209+
p.state = StateStopped // force it into a stopped state
210210
return fmt.Errorf(
211211
"failed to start command and state swap failed. command error: %v, current state: %v, state swap error: %v",
212212
err, curState, swapErr,
@@ -299,6 +299,7 @@ func (p *Process) start() error {
299299
if curState, err := p.swapState(StateStarting, StateReady); err != nil {
300300
return fmt.Errorf("failed to set Process state to ready: current state: %v, error: %v", curState, err)
301301
} else {
302+
p.failedStartCount = 0
302303
return nil
303304
}
304305
}
@@ -323,18 +324,9 @@ func (p *Process) StopImmediately() {
323324
}
324325

325326
p.proxyLogger.Debugf("<%s> Stopping process, current state: %s", p.ID, p.CurrentState())
326-
currentState := p.CurrentState()
327-
328-
if currentState == StateFailed {
329-
if curState, err := p.swapState(StateFailed, StateStopping); err != nil {
330-
p.proxyLogger.Infof("<%s> Stop() Failed -> StateStopping err: %v, current state: %v", p.ID, err, curState)
331-
return
332-
}
333-
} else {
334-
if curState, err := p.swapState(StateReady, StateStopping); err != nil {
335-
p.proxyLogger.Infof("<%s> Stop() Ready -> StateStopping err: %v, current state: %v", p.ID, err, curState)
336-
return
337-
}
327+
if curState, err := p.swapState(StateReady, StateStopping); err != nil {
328+
p.proxyLogger.Infof("<%s> Stop() Ready -> StateStopping err: %v, current state: %v", p.ID, err, curState)
329+
return
338330
}
339331

340332
p.stopCommand()
@@ -401,7 +393,7 @@ func (p *Process) ProxyRequest(w http.ResponseWriter, r *http.Request) {
401393

402394
// prevent new requests from being made while stopping or irrecoverable
403395
currentState := p.CurrentState()
404-
if currentState == StateFailed || currentState == StateShutdown || currentState == StateStopping {
396+
if currentState == StateShutdown || currentState == StateStopping {
405397
http.Error(w, fmt.Sprintf("Process can not ProxyRequest, state is %s", currentState), http.StatusServiceUnavailable)
406398
return
407399
}

proxy/process_test.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ func TestProcess_BrokenModelConfig(t *testing.T) {
106106

107107
w = httptest.NewRecorder()
108108
process.ProxyRequest(w, req)
109-
assert.Equal(t, http.StatusServiceUnavailable, w.Code)
110-
assert.Contains(t, w.Body.String(), "Process can not ProxyRequest, state is failed")
109+
assert.Equal(t, http.StatusBadGateway, w.Code)
110+
assert.Contains(t, w.Body.String(), "start() failed: ")
111111
}
112112

113113
func TestProcess_UnloadAfterTTL(t *testing.T) {
@@ -248,18 +248,14 @@ func TestProcess_SwapState(t *testing.T) {
248248
}{
249249
{"Stopped to Starting", StateStopped, StateStopped, StateStarting, nil, StateStarting},
250250
{"Starting to Ready", StateStarting, StateStarting, StateReady, nil, StateReady},
251-
{"Starting to Failed", StateStarting, StateStarting, StateFailed, nil, StateFailed},
252251
{"Starting to Stopping", StateStarting, StateStarting, StateStopping, nil, StateStopping},
252+
{"Starting to Stopped", StateStarting, StateStarting, StateStopped, nil, StateStopped},
253253
{"Ready to Stopping", StateReady, StateReady, StateStopping, nil, StateStopping},
254254
{"Stopping to Stopped", StateStopping, StateStopping, StateStopped, nil, StateStopped},
255255
{"Stopping to Shutdown", StateStopping, StateStopping, StateShutdown, nil, StateShutdown},
256256
{"Stopped to Ready", StateStopped, StateStopped, StateReady, ErrInvalidStateTransition, StateStopped},
257-
{"Starting to Stopped", StateStarting, StateStarting, StateStopped, ErrInvalidStateTransition, StateStarting},
258257
{"Ready to Starting", StateReady, StateReady, StateStarting, ErrInvalidStateTransition, StateReady},
259-
{"Ready to Failed", StateReady, StateReady, StateFailed, ErrInvalidStateTransition, StateReady},
260258
{"Stopping to Ready", StateStopping, StateStopping, StateReady, ErrInvalidStateTransition, StateStopping},
261-
{"Failed to Stopped", StateFailed, StateFailed, StateStopped, ErrInvalidStateTransition, StateFailed},
262-
{"Failed to Starting", StateFailed, StateFailed, StateStarting, ErrInvalidStateTransition, StateFailed},
263259
{"Shutdown to Stopped", StateShutdown, StateShutdown, StateStopped, ErrInvalidStateTransition, StateShutdown},
264260
{"Shutdown to Starting", StateShutdown, StateShutdown, StateStarting, ErrInvalidStateTransition, StateShutdown},
265261
{"Expected state mismatch", StateStopped, StateStarting, StateStarting, ErrExpectedStateMismatch, StateStopped},

proxy/proxymanager.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,8 +348,6 @@ func (pm *ProxyManager) upstreamIndex(c *gin.Context) {
348348
stateStr = "Starting"
349349
case StateStopping:
350350
stateStr = "Stopping"
351-
case StateFailed:
352-
stateStr = "Failed"
353351
case StateShutdown:
354352
stateStr = "Shutdown"
355353
case StateStopped:

0 commit comments

Comments
 (0)