This is an automated email from the ASF dual-hosted git repository.

rabbah pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk.git


The following commit(s) were added to refs/heads/master by this push:
     new 6d17625  Display proper error when sequence invocation fails due to 
missing component (#3799)
6d17625 is described below

commit 6d17625dd9de8ae693fae26508de2b97437d7e97
Author: James Dubee <jwdu...@us.ibm.com>
AuthorDate: Mon Jul 30 19:16:00 2018 -0400

    Display proper error when sequence invocation fails due to missing 
component (#3799)
---
 .../core/controller/actions/SequenceActions.scala  | 22 +++++++++----
 .../core/controller/test/SequenceApiTests.scala    | 38 ++++++++++++++++++----
 2 files changed, 47 insertions(+), 13 deletions(-)

diff --git 
a/core/controller/src/main/scala/whisk/core/controller/actions/SequenceActions.scala
 
b/core/controller/src/main/scala/whisk/core/controller/actions/SequenceActions.scala
index dd3e331..cd6c1ea 100644
--- 
a/core/controller/src/main/scala/whisk/core/controller/actions/SequenceActions.scala
+++ 
b/core/controller/src/main/scala/whisk/core/controller/actions/SequenceActions.scala
@@ -34,6 +34,7 @@ import whisk.common.Logging
 import whisk.common.TransactionId
 import whisk.core.controller.WhiskServices
 import whisk.core.database.ActivationStore
+import whisk.core.database.NoDocumentException
 import whisk.core.entity._
 import whisk.core.entity.size.SizeInt
 import whisk.core.entity.types._
@@ -259,14 +260,21 @@ protected[actions] trait SequenceActions {
       .foldLeft(initialAccounting) { (accountingFuture, futureAction) =>
         accountingFuture.flatMap { accounting =>
           if (accounting.atomicActionCnt < actionSequenceLimit) {
-            invokeNextAction(user, futureAction, accounting, cause).flatMap { 
accounting =>
-              if (!accounting.shortcircuit) {
-                Future.successful(accounting)
-              } else {
-                // this is to short circuit the fold
-                Future.failed(FailedSequenceActivation(accounting)) // 
terminates the fold
+            invokeNextAction(user, futureAction, accounting, cause)
+              .flatMap { accounting =>
+                if (!accounting.shortcircuit) {
+                  Future.successful(accounting)
+                } else {
+                  // this is to short circuit the fold
+                  Future.failed(FailedSequenceActivation(accounting)) // 
terminates the fold
+                }
+              }
+              .recoverWith {
+                case _: NoDocumentException =>
+                  val updatedAccount =
+                    
accounting.fail(ActivationResponse.applicationError(sequenceComponentNotFound), 
None)
+                  Future.failed(FailedSequenceActivation(updatedAccount)) // 
terminates the fold
               }
-            }
           } else {
             val updatedAccount = 
accounting.fail(ActivationResponse.applicationError(sequenceIsTooLong), None)
             Future.failed(FailedSequenceActivation(updatedAccount)) // 
terminates the fold
diff --git 
a/tests/src/test/scala/whisk/core/controller/test/SequenceApiTests.scala 
b/tests/src/test/scala/whisk/core/controller/test/SequenceApiTests.scala
index 9784278..5bc1996 100644
--- a/tests/src/test/scala/whisk/core/controller/test/SequenceApiTests.scala
+++ b/tests/src/test/scala/whisk/core/controller/test/SequenceApiTests.scala
@@ -19,22 +19,19 @@ package whisk.core.controller.test
 
 import scala.concurrent.duration.DurationInt
 import scala.language.postfixOps
-
+import java.time.Instant
 import org.junit.runner.RunWith
 import org.scalatest.junit.JUnitRunner
-
 import akka.http.scaladsl.model.StatusCodes._
 import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
 import akka.http.scaladsl.server.Route
-
 import spray.json._
 import spray.json.DefaultJsonProtocol._
-
 import whisk.common.TransactionId
 import whisk.core.controller.WhiskActionsApi
 import whisk.core.entity._
-import whisk.http.ErrorResponse
-import whisk.http.Messages
+import whisk.http.{ErrorResponse, Messages}
+import whisk.http.Messages.sequenceComponentNotFound
 
 /**
  * Tests Sequence API - stand-alone tests that require only the controller to 
be up
@@ -53,6 +50,35 @@ class SequenceApiTests extends ControllerTestCommon with 
WhiskActionsApi {
 
   val allowedActionDuration = 120 seconds
 
+  it should "partially invoke a sequence with missing component and produce 
component missing error" in {
+    implicit val tid = transid()
+    val seqName = s"${aname()}_seq"
+    val compName1 = s"${aname()}_comp1"
+    val compName2 = s"${aname()}_comp2"
+    val comp1Activation = WhiskActivation(
+      namespace,
+      EntityName(compName1),
+      creds.subject,
+      activationIdFactory.make(),
+      start = Instant.now,
+      end = Instant.now)
+
+    putSimpleSequenceInDB(seqName, namespace, Vector(compName1, compName2))
+    deleteAction(DocId(s"$namespace/$compName2"))
+    loadBalancer.whiskActivationStub = Some((1.milliseconds, comp1Activation))
+
+    Post(s"$collectionPath/$seqName?blocking=true") ~> 
Route.seal(routes(creds)) ~> check {
+      deleteAction(DocId(s"$namespace/$seqName"))
+      deleteAction(DocId(s"$namespace/$compName1"))
+      status should be(BadGateway)
+      val response = responseAs[JsObject]
+      response.fields("response") shouldBe 
ActivationResponse.applicationError(sequenceComponentNotFound).toExtendedJson
+      val logs = response.fields("logs").convertTo[JsArray]
+      logs.elements.size shouldBe 1
+      logs.elements.head shouldBe comp1Activation.activationId.toJson
+    }
+  }
+
   it should "reject creation of sequence with more actions than allowed limit" 
in {
     implicit val tid = transid()
     val seqName = EntityName(s"${aname()}_toomanyactions")

Reply via email to