@@ -458,7 +458,13 @@ class ContainerProxy(factory: (TransactionId,
458458 destroyContainer(newData, true )
459459
460460 // Failed after /init (the first run failed) on prewarmed or cold start
461+ // - container will be destroyed
462+ // - buffered will be aborted (if init fails, we assume it will always fail)
461463 case Event (f : FailureMessage , data : PreWarmedData ) =>
464+ logging.error(
465+ this ,
466+ s " Failed during init of cold container ${data.getContainer}, queued activations will be aborted. " )
467+
462468 activeCount -= 1
463469 // reuse an existing init failure for any buffered activations that will be aborted
464470 val r = f.cause match {
@@ -468,7 +474,12 @@ class ContainerProxy(factory: (TransactionId,
468474 destroyContainer(data, true , true , r)
469475
470476 // Failed for a subsequent /run
477+ // - container will be destroyed
478+ // - buffered will be resent (at least 1 has completed, so others are given a chance to complete)
471479 case Event (_ : FailureMessage , data : WarmedData ) =>
480+ logging.error(
481+ this ,
482+ s " Failed during use of warm container ${data.getContainer}, queued activations will be resent. " )
472483 activeCount -= 1
473484 if (activeCount == 0 ) {
474485 destroyContainer(data, true )
@@ -479,10 +490,13 @@ class ContainerProxy(factory: (TransactionId,
479490 }
480491
481492 // Failed at getting a container for a cold-start run
493+ // - container will be destroyed
494+ // - buffered will be aborted (if cold start container fails to start, we assume it will continue to fail)
482495 case Event (_ : FailureMessage , _) =>
496+ logging.error(this , " Failed to start cold container, queued activations will be aborted." )
483497 activeCount -= 1
484498 context.parent ! ContainerRemoved (true )
485- rejectBuffered ()
499+ abortBuffered ()
486500 stop()
487501
488502 case _ => delay
@@ -649,34 +663,16 @@ class ContainerProxy(factory: (TransactionId,
649663 */
650664 def destroyContainer (newData : ContainerStarted ,
651665 replacePrewarm : Boolean ,
652- abortBuffered : Boolean = false ,
666+ abort : Boolean = false ,
653667 abortResponse : Option [ActivationResponse ] = None ) = {
654668 val container = newData.container
655669 if (! rescheduleJob) {
656670 context.parent ! ContainerRemoved (replacePrewarm)
657671 } else {
658672 context.parent ! RescheduleJob
659673 }
660- if (abortBuffered && runBuffer.length > 0 ) {
661- logging.info(this , s " aborting ${runBuffer.length} queued activations after failed init " )
662- runBuffer.foreach { job =>
663- implicit val tid = job.msg.transid
664- logging.info(this , s " aborting activation ${job.msg.activationId} after failed init with ${abortResponse}" )
665- val result = ContainerProxy .constructWhiskActivation(
666- job,
667- None ,
668- Interval .zero,
669- false ,
670- abortResponse.getOrElse(ActivationResponse .whiskError(Messages .abnormalRun)))
671- val context = UserContext (job.msg.user)
672- val msg = if (job.msg.blocking) {
673- CombinedCompletionAndResultMessage (tid, result, instance)
674- } else {
675- CompletionMessage (tid, result, instance)
676- }
677- sendActiveAck(tid, result, job.msg.blocking, job.msg.rootControllerIndex, job.msg.user.namespace.uuid, msg)
678- storeActivation(tid, result, job.msg.blocking, context)
679- }
674+ if (abort && runBuffer.nonEmpty) {
675+ abortBuffered(abortResponse)
680676 } else {
681677 rejectBuffered()
682678 }
@@ -697,6 +693,35 @@ class ContainerProxy(factory: (TransactionId,
697693 }
698694 }
699695
696+ def abortBuffered (abortResponse : Option [ActivationResponse ] = None ) = {
697+ logging.info(this , s " aborting ${runBuffer.length} queued activations after failed init or failed cold start " )
698+ runBuffer.foreach { job =>
699+ implicit val tid = job.msg.transid
700+ logging.info(
701+ this ,
702+ s " aborting activation ${job.msg.activationId} after failed init or cold start with ${abortResponse}" )
703+ val result = ContainerProxy .constructWhiskActivation(
704+ job,
705+ None ,
706+ Interval .zero,
707+ false ,
708+ abortResponse.getOrElse(ActivationResponse .whiskError(Messages .abnormalRun)))
709+ val context = UserContext (job.msg.user)
710+ val msg = if (job.msg.blocking) {
711+ CombinedCompletionAndResultMessage (tid, result, instance)
712+ } else {
713+ CompletionMessage (tid, result, instance)
714+ }
715+ sendActiveAck(tid, result, job.msg.blocking, job.msg.rootControllerIndex, job.msg.user.namespace.uuid, msg)
716+ .andThen {
717+ case Failure (e) => logging.error(this , s " failed to send abort ack $e" )
718+ }
719+ storeActivation(tid, result, job.msg.blocking, context).andThen {
720+ case Failure (e) => logging.error(this , s " failed to store aborted activation $e" )
721+ }
722+ }
723+ }
724+
700725 /**
701726 * Return any buffered jobs to parent, in case buffer is not empty at removal/error time.
702727 */
0 commit comments