2011-07-13 12 views
6

Mi aplicación actual se basa en akka 1.1. Tiene múltiples ProjectAnalysisActors cada uno responsable de manejar las tareas de análisis para un proyecto específico. El análisis se inicia cuando dicho actor recibe un mensaje de inicio genérico. Después de terminar un paso, se envía un mensaje con el siguiente paso a medida que se define uno. El código que se ejecuta básicamente tiene el siguiente¿Está bien utilizar mensajes bloqueadores de actores cuando están envueltos en un futuro?


sealed trait AnalysisEvent { 
    def run(project: Project): Future[Any] 
    def nextStep: AnalysisEvent = null 
} 

case class StartAnalysis() extends AnalysisEvent { 
    override def run ... 
    override def nextStep: AnalysisEvent = new FirstStep 
} 

case class FirstStep() extends AnalysisEvent { 
    override def run ... 
    override def nextStep: AnalysisEvent = new SecondStep 
} 

case class SecondStep() extends AnalysisEvent { 
    ... 
} 

class ProjectAnalysisActor(project: Project) extends Actor { 

    def receive = { 
     case event: AnalysisEvent => 
      val future = event.run(project) 
      future.onComplete { f => 
       self ! event.nextStep 
      } 
    } 

} 

tengo algunas dificultades cómo implementar el código para el período previo métodos para cada etapa de análisis. Por el momento, creo un nuevo futuro dentro de cada método de ejecución. Dentro de este futuro, envío todos los mensajes de seguimiento a los diferentes subsistemas. Algunos de ellos son mensajes de bloqueo y olvido sin bloqueo, pero algunos devuelven un resultado que debe almacenarse antes de iniciar el siguiente paso de análisis.

En el momento de una carrera método típico tiene el siguiente


def run(project: Project): Future[Any] = { 
    Future { 
     progressActor ! typicalFireAndForget(project.name) 
     val calcResult = (calcActor1 !! doCalcMessage(project)).getOrElse(...) 

     val p: Project = ... // created updated project using calcResult 

     val result = (storage !! updateProjectInformation(p)).getOrElse(...) 
     result 
    } 
} 

Desde esos mensajes de bloqueo deben ser evitados, me pregunto si este es el camino correcto. ¿Tiene sentido usarlos en este caso de uso o debería evitarlo? Si es así, ¿cuál sería la solución adecuada?

Respuesta

7

Aparentemente, el único propósito del ProjectAnalysisActor es encadenar futuras llamadas. En segundo lugar, los métodos de ejecución también parecen esperar los resultados para continuar con los cálculos.

Así que creo que se puede tratar refactorización el código para utilizar futuro Composición, como se explica aquí: http://akka.io/docs/akka/1.1/scala/futures.html

def run(project: Project): Future[Any] = { 
    progressActor ! typicalFireAndForget(project.name) 
    for( 
     calcResult <- calcActor1 !!! doCalcMessage(project); 
     p = ... // created updated project using calcResult 
     result <- storage !!! updateProjectInformation(p) 
) yield (
    result 
) 
} 
+0

Gracias, que parece prometedor. Lo intentaré de inmediato. Tienes razón, el propósito principal es encadenar futuras llamadas. Además de eso, los actores se ocupan de algunas tareas de gestión de análisis de proyectos. – Steffen

+0

Acabo de refactorizar la mayor parte de este código. ¡Funciona perfectamente! – Steffen

Cuestiones relacionadas