2012-07-09 12 views
22

Próbuję wdrożyć długotrwały proces w tle, który jest tworzony, gdy użytkownik odwiedza stronę. Chciałbym wyświetlić postęp zadania tak jak w tym przykładzie: http://web.archive.org/web/20130122091205/http://www.lunatech-research.com/archives/2011/10/31/progressbar-jqueryui-websockets-playframeworkDługi proces uruchamiania z paskiem postępu Przykład PlayFramework 2

Czy ktoś wie o tutorialu dla PlayFramework 2.0 (używając wbudowanej AKKA)? Ten jest dla 1.2

Odpowiedz

21

Po przeczytaniu całej dokumentacji Akka dla Java http://doc.akka.io/docs/akka/2.0.1/intro/getting-started-first-java.html wymyśliłem to, co wydaje się działać dobrze.

System działa po utworzeniu unikalnego aktora, który przetworzy "raport" (po załadowaniu strony generującej). Ten aktor spawnuje aktora dziecka, który przekazuje informacje o jego postępach rodzicowi. Aktor nadrzędny jest następnie odpytywany przez JavaScript w celu sprawdzenia statusu wątku podrzędnego.

Po zakończeniu procesu dziecko zostaje zakończone, a gdy rodzic wykryje, że dziecko zostało ukończone, kończy się samo.

Poniżej znajduje się cały kod, nie krępuj się, by rozerwać mnie na strzępy, jeśli zrobiłem to w niewłaściwy sposób! (To jest ok, aby zapisać stan w Actors?!?)

Kod Kontroler:

public class Application extends Controller { 


public static Result generateReport() 
{ 
    //create akka job 

    //we should really create the actor with UUID name so that someone can't guess 
    //and use the API to view the status of other peoples jobs, it be fairly easy 
    //to guess as it goes $a,$b,$c etc... 
    ActorRef myActor = Akka.system().actorOf(new Props(MyGeneratorMaster.class)); 

    System.out.println(myActor.path()); 
    myActor.tell(new ConfigMessage("blarg message")); 

    return ok(generating.render("blarg","title",myActor.path().name())); 
} 

public static Result status(String uuid) 
{ 
    uuid = "akka://application/user/"+uuid; 
    ActorRef myActor = Akka.system().actorFor(uuid); 

    if(myActor.isTerminated()) 
    { 
       return ok("Report Generated - All Actors Terminated") ; 
    } 
    else 
    { 

     return async(
       Akka.asPromise(ask(myActor,new StatusMessage(), 3000)).map(
         new F.Function<Object,Result>() { 
          public Result apply(Object response) { 

           if(response instanceof ResultMessage) 
           { 
            return ok(((ResultMessage) response).getResult()); 
           } 
           return ok(response.toString()); 
          } 
         } 
       ) 
     ); 

    } 
} 

Aktor Master:

public class MyGeneratorMaster extends UntypedActor { 

    private int completed = 0; 

    @Override 
    public void postStop() { 
     super.postStop(); 
     System.out.println("Master Killed"); 
    } 

    @Override 
    public void onReceive(Object message) throws Exception { 
     if (message instanceof actors.messages.ConfigMessage) { 
      ConfigMessage config = (ConfigMessage) message; 

      System.out.println("Received Config:" + config.getConfig()); 

      //Need to spawn child actor here.. 
      ActorRef child = this.getContext().actorOf(new Props(MyGeneratorChildWorker.class)); 

      //make the child thread do stuff 
      child.tell(new ConfigMessage("doSomething!")); 

      child.tell(akka.actor.PoisonPill.getInstance());//kill the child after the work is complete... 

     } else if (message instanceof StatusUpdate) { 
      System.out.println("Got Status Update"); 
      completed = ((StatusUpdate) message).getProgress(); 
     } else if (message instanceof StatusMessage) { 
      System.out.println("Got Status Message"); 
      getSender().tell(new ResultMessage("Status: " + completed + "%"), getSelf()); 

      if(completed == 100) 
      { 
       //kill this actor, we're done! 
       //could also call stop... 
       this.getSelf().tell(akka.actor.PoisonPill.getInstance()); 
      } 
     } else { 
      System.out.println("unhandled message"+message.toString()); 
      unhandled(message); 
     } 

    } 
} 

Aktor dziecka:

public class MyGeneratorChildWorker extends UntypedActor { 

    @Override 
    public void postStop() { 
     super.postStop();  
     System.out.println("Child Killed"); 
    } 

    @Override 
    public void onReceive(Object message) throws Exception { 

     if (message instanceof ConfigMessage) { 

      System.out.println("Created Child Worker"); 

      System.out.println("Doing Work:"); 
      try { 

       for (int i = 0; i <= 100; i++) { 


        //update parent 
        this.context().parent().tell(new StatusUpdate(i)); 
        long j = 1; 
        //waste loads of cpu cycles 
        while (j < 1E8) { 
         j = j + 1; 
        } 
       } 
      } catch (Exception ex) { 

      } 
      System.out.println("Done Work:"); 


     } else 
      unhandled(message); 
    } 
} 

Strona widoku z długą ankietą JavaScript:

@(message: String)(title: String)(id: String)@main(title) { 

<h2>@message</h2> 

     <script type="text/javascript"> 

      function getPercentage() 
      { 

       $.ajax({ 
        type: "GET", 
        url: "/status/@id", 
        dataType: "html", 
        success: function(html) 
         { 
         $('#status').html(html); 


         } 
       }); 

      } 

      $(document).ready(function() { 


      setInterval("getPercentage()",100); 
      }); 



     </script> 

     <div id="status"> 

     </div> 

} 
+2

Wygląda dobrze, spróbuję. Gra jest świetna, ale takie rzeczy mają bardzo małe próbki kodu. – Steve

+3

Wiem, to bardzo frustrujące! –

+1

"Czy można zapisać stan w Actors?!?" Aktorzy są jednym z niewielu miejsc, w których można przechowywać państwo. – EECOLOR

Powiązane problemy