@@ -618,8 +618,8 @@ func (mtask *managedTask) progressContainers() {
618
618
// We've kicked off one or more transitions, wait for them to
619
619
// complete, but keep reading events as we do. in fact, we have to for
620
620
// transitions to complete
621
- mtask .waitForContainerTransitions (transitions , transitionChange , transitionChangeContainer )
622
- seelog .Debugf ("Managed task [%s]: done transitioning all containers " , mtask .Arn )
621
+ mtask .waitForContainerTransition (transitions , transitionChange , transitionChangeContainer )
622
+ seelog .Debugf ("Managed task [%s]: wait for container transition done " , mtask .Arn )
623
623
624
624
// update the task status
625
625
changed := mtask .UpdateStatus ()
@@ -663,16 +663,30 @@ func (mtask *managedTask) startContainerTransitions(transitionFunc containerTran
663
663
reasons = append (reasons , transition .reason )
664
664
continue
665
665
}
666
+
667
+ // If the container is already in a transition, skip
668
+ if transition .actionRequired && ! cont .SetAppliedStatus (transition .nextState ) {
669
+ // At least one container is able to be moved forwards, so we're not deadlocked
670
+ anyCanTransition = true
671
+ continue
672
+ }
673
+
666
674
// At least one container is able to be moved forwards, so we're not deadlocked
667
675
anyCanTransition = true
668
676
669
677
if ! transition .actionRequired {
670
- mtask .handleContainerChange (dockerContainerChange {
671
- container : cont ,
672
- event : DockerContainerChangeEvent {
673
- Status : transition .nextState ,
674
- },
675
- })
678
+ // Updating the container status without calling any docker API, send in
679
+ // a goroutine so that it won't block here before the waitForContainerTransition
680
+ // was called after this function. And all the events sent to mtask.dockerMessages
681
+ // will be handled by handleContainerChange.
682
+ go func (cont * api.Container , status api.ContainerStatus ) {
683
+ mtask .dockerMessages <- dockerContainerChange {
684
+ container : cont ,
685
+ event : DockerContainerChangeEvent {
686
+ Status : status ,
687
+ },
688
+ }
689
+ }(cont , transition .nextState )
676
690
continue
677
691
}
678
692
transitions [cont .Name ] = transition .nextState
@@ -763,39 +777,23 @@ func (mtask *managedTask) onContainersUnableToTransitionState() {
763
777
mtask .emitTaskEvent (mtask .Task , taskUnableToTransitionToStoppedReason )
764
778
// TODO we should probably panic here
765
779
} else {
766
- seelog .Criticalf ("Managed task [%s]: voving task to stopped due to bad state" , mtask .Arn )
780
+ seelog .Criticalf ("Managed task [%s]: moving task to stopped due to bad state" , mtask .Arn )
767
781
mtask .handleDesiredStatusChange (api .TaskStopped , 0 )
768
782
}
769
783
}
770
784
771
- func (mtask * managedTask ) waitForContainerTransitions (transitions map [string ]api.ContainerStatus ,
785
+ func (mtask * managedTask ) waitForContainerTransition (transitions map [string ]api.ContainerStatus ,
772
786
transitionChange <- chan struct {},
773
787
transitionChangeContainer <- chan string ) {
774
-
775
- for len (transitions ) > 0 {
776
- if mtask .waitEvent (transitionChange ) {
777
- changedContainer := <- transitionChangeContainer
778
- seelog .Debugf ("Managed task [%s]: transition for container[%s] finished" ,
779
- mtask .Arn , changedContainer )
780
- delete (transitions , changedContainer )
781
- seelog .Debugf ("Managed task [%s]: still waiting for: %v" , mtask .Arn , transitions )
782
- }
783
- if mtask .GetDesiredStatus ().Terminal () || mtask .GetKnownStatus ().Terminal () {
784
- allWaitingOnPulled := true
785
- for _ , desired := range transitions {
786
- if desired != api .ContainerPulled {
787
- allWaitingOnPulled = false
788
- }
789
- }
790
- if allWaitingOnPulled {
791
- // We don't actually care to wait for 'pull' transitions to finish if
792
- // we're just heading to stopped since those resources aren't
793
- // inherently linked to this task anyways for e.g. gc and so on.
794
- seelog .Debugf ("Managed task [%s]: all containers are waiting for pulled transition; exiting early: %v" ,
795
- mtask .Arn , transitions )
796
- break
797
- }
798
- }
788
+ // There could be multiple transitions, but we just need to wait for one of them
789
+ // to ensure that there is at least one container can be processed in the next
790
+ // progressContainers. This is done by waiting for one transition/acs/docker message.
791
+ if mtask .waitEvent (transitionChange ) {
792
+ changedContainer := <- transitionChangeContainer
793
+ seelog .Debugf ("Managed task [%s]: transition for container[%s] finished" ,
794
+ mtask .Arn , changedContainer )
795
+ delete (transitions , changedContainer )
796
+ seelog .Debugf ("Managed task [%s]: still waiting for: %v" , mtask .Arn , transitions )
799
797
}
800
798
}
801
799
0 commit comments