@@ -77,47 +77,57 @@ func (pool *ApplicationPool) _getPodNoLock(podName string) *ApplicationPod {
7777 return nil
7878}
7979
80+ func (pool * ApplicationPool ) podStateTransitionAllowed (oldState , newState ApplicationPodState ) bool {
81+ if oldState == newState {
82+ return true
83+ } else if oldState == PodStatePending {
84+ return true
85+ } else if oldState == PodStateIdle && newState != PodStatePending {
86+ return true
87+ } else if oldState == PodStateAllocated && newState != PodStatePending {
88+ return true
89+ } else if oldState == PodStateDeleting && newState == PodStateDeleting {
90+ return true
91+ }
92+ return false
93+ }
94+
8095// find pod in a state map, move it to different state map and add session bundle on it
81- func (pool * ApplicationPool ) addOrUpdatePod (podName string , podState ApplicationPodState , sessionIds []string ) * ApplicationPod {
96+ func (pool * ApplicationPool ) addOrUpdatePod (podName string , podState ApplicationPodState , sessionNames []string ) * ApplicationPod {
8297 pool .mu .Lock ()
8398 defer pool .mu .Unlock ()
8499 if p := pool ._getPodNoLock (podName ); p != nil {
85- // pod state should not be reverted to avoid race condition
86- if p .state == PodStateDeleting && podState != PodStateDeleting {
87- // do not change a pod state already marked as deleting pods
88- return p
89- }
90- if p .state != PodStatePending && podState == PodStatePending {
91- // do not change a pod state to pending if pod is not pending anymore
100+ if ! pool .podStateTransitionAllowed (p .state , podState ) {
92101 return p
93102 }
94103 }
95- return pool ._addOrUpdatePodNoLock (podName , podState , sessionIds )
104+ return pool ._addOrUpdatePodNoLock (podName , podState , sessionNames )
96105}
97106
98- func (pool * ApplicationPool ) _addOrUpdatePodNoLock (podName string , podState ApplicationPodState , sessionIds []string ) * ApplicationPod {
107+ // move pod from a state bucket to new state bucket and update its session map
108+ func (pool * ApplicationPool ) _addOrUpdatePodNoLock (podName string , podNewState ApplicationPodState , sessionNames []string ) * ApplicationPod {
99109 for _ , pods := range pool .podsByState {
100110 if p , f := pods [podName ]; f {
101- for _ , v := range sessionIds {
111+ for _ , v := range sessionNames {
102112 p .sessions [v ] = true
103113 }
104- if p .state == podState {
114+ if p .state == podNewState {
105115 return p
106116 } else {
107- p .state = podState
108- pool.podsByState [podState ][podName ] = p
117+ p .state = podNewState
118+ pool.podsByState [podNewState ][podName ] = p
109119 delete (pods , podName )
110120 return p
111121 }
112122 }
113123 }
114124
115125 // not found, add it
116- p := NewApplicationPod (podName , podState )
117- for _ , v := range sessionIds {
126+ p := NewApplicationPod (podName , podNewState )
127+ for _ , v := range sessionNames {
118128 p .sessions [v ] = true
119129 }
120- pool.podsByState [podState ][podName ] = p
130+ pool.podsByState [podNewState ][podName ] = p
121131 return p
122132}
123133
@@ -220,32 +230,8 @@ func (pool *ApplicationPool) summarySession() ApplicationSessionSummary {
220230 summary .deletingCount = len (pool .sessions [SessionStateDeleting ])
221231 summary .runningCount = len (pool .sessions [SessionStateRunning ])
222232 summary .startingCount = len (pool .sessions [SessionStateStarting ])
233+ summary .pendingCount = len (pool .sessions [SessionStatePending ])
223234
224- for _ , s := range pool .sessions [SessionStatePending ] {
225- timeoutDuration := DefaultSessionOpenTimeoutDuration
226- if s .session .Spec .OpenTimeoutSeconds > 0 {
227- timeoutDuration = time .Duration (s .session .Spec .OpenTimeoutSeconds ) * time .Second
228- }
229- pendingTimeoutTimeStamp := time .Now ().Add (- 1 * timeoutDuration )
230- if s .session .CreationTimestamp .Time .Before (pendingTimeoutTimeStamp ) {
231- summary .timeoutCount += 1
232- } else {
233- summary .pendingCount += 1
234- }
235- }
236-
237- for _ , s := range pool .sessions [SessionStateStarting ] {
238- timeoutDuration := DefaultSessionOpenTimeoutDuration
239- if s .session .Spec .OpenTimeoutSeconds > 0 {
240- timeoutDuration = time .Duration (s .session .Spec .OpenTimeoutSeconds ) * time .Second
241- }
242- pendingTimeoutTimeStamp := time .Now ().Add (- 1 * timeoutDuration )
243- if s .session .CreationTimestamp .Time .Before (pendingTimeoutTimeStamp ) {
244- summary .timeoutCount += 1
245- } else {
246- summary .startingCount += 1
247- }
248- }
249235 return summary
250236}
251237
@@ -265,59 +251,74 @@ func (pool *ApplicationPool) _getSessionNoLock(key string) *ApplicationSession {
265251 return nil
266252}
267253
268- func (pool * ApplicationPool ) addSession (sessionId string , session * fornaxv1.ApplicationSession ) {
254+ func (pool * ApplicationPool ) addSession (sessionName string , session * fornaxv1.ApplicationSession ) {
269255 pool .mu .Lock ()
270256 defer pool .mu .Unlock ()
271257 newState := SessionStatePending
272- if session .DeletionTimestamp != nil {
258+ if session .DeletionTimestamp != nil || util . SessionIsClosing ( session ) {
273259 newState = SessionStateDeleting
274- } else if util .SessionIsOpen (session ) {
275- newState = SessionStateRunning
276260 } else if util .SessionIsStarting (session ) {
277261 newState = SessionStateStarting
278262 } else if util .SessionIsPending (session ) {
279263 newState = SessionStatePending
280- } else if util .SessionIsClosing (session ) {
281- newState = SessionStateDeleting
264+ } else if util .SessionIsOpen (session ) {
265+ newState = SessionStateRunning
282266 } else {
283- // do not add a terminal state session, instead of deleting and return
284267 pool ._deleteSessionNoLock (session )
285268 return
286269 }
287270
288- s := pool ._getSessionNoLock (sessionId )
271+ s := pool ._getSessionNoLock (sessionName )
289272 if s != nil {
290- if newState != s .state {
291- delete (pool .sessions [s .state ], sessionId )
273+ if pool .sessionStateTransitionAllowed (s .state , newState ) {
274+ delete (pool .sessions [s .state ], sessionName )
275+ } else {
276+ return
292277 }
293278 }
294279
295280 // update pool with new state
296- pool.sessions [newState ][sessionId ] = & ApplicationSession {
281+ pool.sessions [newState ][sessionName ] = & ApplicationSession {
297282 session : session ,
298283 state : newState ,
299284 }
300285 if session .Status .PodReference != nil {
301286 podName := session .Status .PodReference .Name
302- pool ._addOrUpdatePodNoLock (podName , PodStateAllocated , []string {string ( session . GetUID ()) })
287+ pool ._addOrUpdatePodNoLock (podName , PodStateAllocated , []string {sessionName })
303288 }
304289}
305290
291+ func (pool * ApplicationPool ) sessionStateTransitionAllowed (oldState , newState ApplicationSessionState ) bool {
292+ if oldState == newState {
293+ return true
294+ } else if oldState == SessionStatePending {
295+ return true
296+ } else if oldState == SessionStateStarting && newState != SessionStatePending {
297+ return true
298+ } else if oldState == SessionStateRunning && newState != SessionStatePending && newState != SessionStateStarting {
299+ return true
300+ } else if oldState == SessionStateDeleting && newState != SessionStatePending && newState != SessionStateStarting && newState != SessionStateRunning {
301+ return true
302+ }
303+ return false
304+ }
305+
306306func (pool * ApplicationPool ) deleteSession (session * fornaxv1.ApplicationSession ) {
307307 pool .mu .Lock ()
308308 defer pool .mu .Unlock ()
309309 pool ._deleteSessionNoLock (session )
310310}
311311
312+ // delete a session from application pool, and delete it from referenced pod's session map, and change pod state back to idle state,
313+ // only allow from allocated => idle when delete a session from this pod, pod is in pending/deleting state should keep its state
312314func (pool * ApplicationPool ) _deleteSessionNoLock (session * fornaxv1.ApplicationSession ) {
313- sessionId := string ( session . GetUID () )
315+ sessionName := util . Name ( session )
314316 if session .Status .PodReference != nil {
315317 podName := session .Status .PodReference .Name
316318 for _ , podsOfState := range pool .podsByState {
317319 if pod , found := podsOfState [podName ]; found {
318- delete (pod .sessions , sessionId )
320+ delete (pod .sessions , sessionName )
319321 if len (pod .sessions ) == 0 && pod .state == PodStateAllocated {
320- // only allow from allocated => idle when delete a session from this pod, pod is in pending/deleting state should keep its state
321322 delete (podsOfState , podName )
322323 pod .state = PodStateIdle
323324 pool.podsByState [PodStateIdle ][podName ] = pod
@@ -327,14 +328,14 @@ func (pool *ApplicationPool) _deleteSessionNoLock(session *fornaxv1.ApplicationS
327328 }
328329 }
329330 for _ , v := range pool .sessions {
330- delete (v , sessionId )
331+ delete (v , sessionName )
331332 }
332333}
333334
334335// getNonRunningSessions return a list of session of different states,
335- // pending, not assigned to pod yet
336- // deleting, delete requested
337- // timeout, session timedout to get a pod, or session assigned to node, but timeout to get session state from node
336+ // 1/ pending, not assigned to pod yet
337+ // 2/ deleting, delete requested
338+ // 3/ timeout, session timedout to get a pod, or session assigned to node, but timeout to get session state from node
338339func (pool * ApplicationPool ) getNonRunningSessions () (pendingSessions , deletingSessions , timeoutSessions []* ApplicationSession ) {
339340 pool .mu .RLock ()
340341 defer pool .mu .RUnlock ()
@@ -360,8 +361,6 @@ func (pool *ApplicationPool) getNonRunningSessions() (pendingSessions, deletingS
360361 pendingTimeoutTimeStamp := time .Now ().Add (- 1 * timeoutDuration )
361362 if s .session .CreationTimestamp .Time .Before (pendingTimeoutTimeStamp ) {
362363 timeoutSessions = append (timeoutSessions , s )
363- } else {
364- pendingSessions = append (pendingSessions , s )
365364 }
366365 }
367366
@@ -375,13 +374,13 @@ func (pool *ApplicationPool) getNonRunningSessions() (pendingSessions, deletingS
375374// add active session into application's session pool and delete terminal session from pool
376375// add session/delete session will update pod state according pod's session usage
377376func updateSessionPool (pool * ApplicationPool , session * fornaxv1.ApplicationSession ) {
378- sessionId := string ( session . GetUID () )
377+ sessionName := util . Name ( session )
379378 if util .SessionInTerminalState (session ) {
380379 pool .deleteSession (session )
381380 } else {
382381 // a trick to make sure pending session are sorted using micro second, api server truncate creation timestamp to second
383382 session .CreationTimestamp = * util .NewCurrentMetaTime ()
384- pool .addSession (sessionId , session )
383+ pool .addSession (sessionName , session )
385384 }
386385}
387386
0 commit comments