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))
})
}