def runNextActorInSequence()

in app/services/actors/ProjectCreationActor.scala [48:78]


  def runNextActorInSequence(actorSequence:Seq[ActorRef], rq:ProjectRequestFull, data:ProjectCreateTransientData):Future[Either[StepFailed,StepSucceded]] = {
    if(actorSequence.isEmpty) return Future(Right(StepSucceded(data)))

    val resultFuture = actorSequence.head ? NewProjectRequest(rq, None,data)
    resultFuture.onComplete({ //use this to catch exceptions
      case Success(result)=>logger.debug(s"actor ask success: $result")
      case Failure(error)=>logger.debug(s"actor ask failure: $error")
    })

    resultFuture.flatMap({
      case successMessage:StepSucceded=>
        logger.debug("stepSucceeded, running next actor in sequence")
        runNextActorInSequence(actorSequence.tail, rq,successMessage.updatedData) flatMap {
          case Left(failedMessage)=>  //if the _next_ step fails, tell this step to roll back
            (actorSequence.head ? NewProjectRollback(rq, successMessage.updatedData)).map(result=>Left(failedMessage))
          case Right(nextActorSuccess)=>
            Future(Right(nextActorSuccess))
        }
      case failedMessage:StepFailed=> //if the step fails, tell it to roll back
        logger.warn(s"StepFailed, sending rollback to ${actorSequence.head}")
        //don't actually care about the result of rollback, but do care about sequencing
        (actorSequence.head ? NewProjectRollback(rq, failedMessage.updatedData)).map(result=>Left(failedMessage))
      case other:Any=>
        logger.error(s"got unexpected message: ${other.getClass}")
        Future(Left(StepFailed(data, new RuntimeException("got unexpected message"))))
    }).recover({
      case err:Throwable=>
        logger.error(s"Actor ask failed for ${actorSequence.head.path.toString}: ", err)
        Left(StepFailed(data, err))
    })
  }