2016-07-14 6 views
0

Angenommen, ich habe einen Arbeiterdarsteller, der eine Nachricht empfängt, ein wenig verarbeitet und ein Ergebnis zurückgibt. Und ich habe eine Folge von Nachrichten, die in eine Folge von Ergebnissen umgesetzt werden müssen:So kompilieren Sie eine Sequenz von Ergebnissen mit ask pattern

object Test { 

    case class Message(str: String) 
    case class Result(str: String) 

    class Worker extends Actor { 
    def receive = { 
     case Message(data) => 
      println("Sleeping: " + data) 
      Thread.sleep(10000) 
      val result = Result(data + " - result") 
      println("Sending result: " + result) 
      sender ! result 
    } 
    } 

    def test(messages: Seq[Message]): Future[Seq[Result]] = { 
    val worker = ActorSystem().actorOf(Props(new Worker)) 
    val results = messages.map { m => 
     implicit val timeout = Timeout(20 seconds) 
     println("Sending: " + m) 
     val result = worker ? m 
     result.asInstanceOf[Future[Result]] 
    } 
    Future.sequence(results) 
    } 

    def main(args: Array[String]): Unit = { 
    val messages: Seq[Message] = args.map(Message(_)) 
    test(messages).foreach { r => 
     println("Result: " + r) 
    } 
} 

}

Wenn ich die oben mit nur „-Meldung-1“ als Argument laufen läuft es in Ordnung gibt die der Ausgang ist unten:

Senden: Nachricht (message-1)

Schlafen: Meldung-1

Se Ergebnis nden: Ergebnis (message-1 - Ergebnis)

Ergebnis: ArraySeq (Ergebnis (message-1 - Ergebnis))

jedoch sagen, ich tue es mit: "message-1" „message-2 " "message-3", dann die letzte Nachricht endet als an deadLetters gesendet:

Senden: Nachricht (message-1) Senden: Nachricht (message-2) Schlafen: message-1 gesendet: Nachricht (message -3)

Ergebnis senden: Ergebnis (message-1 - Ergebnis)

Schlafen: Meldung-2

Senden Ergebnis: Ergebnis (message-2 - Ergebnis)

Schlafen: Meldung-3

Senden Ergebnis: Ergebnis (message-3 - Ergebnis)

[INFO] [07/15/2016 09: 07: 49.832] [default-akka.actor.default-dispatcher-2] [akka: // default/deadLetters] Nachricht [util.Tester $ Result] from Darsteller [akka: // default/user/$ a # 1776546850] zu Actor [akka: // default/deadLetters] wurde nicht zugestellt. [1] Tote Buchstaben angetroffen. Diese Protokollierung kann mit Konfigurationseinstellungen 'akka.log-dead-letters' und 'akka.log-dead-letters-when-shutdown' ausgeschaltet oder angepasst werden.

Ich vermute, das liegt daran, dass mein Aufruf-Thread zum Zeitpunkt des letzten Sendens der Nachricht nicht mehr verfügbar ist. Wie können alle Ergebnisse korrekt in einer Sequenz gesammelt werden?

Beachten Sie, dass auf unter meiner Testmethode ändert die gleichen Ergebnisse erzielen lassen:

def test(messages: Seq[Message]): Future[Seq[Result]] = { 
    val worker = ActorSystem().actorOf(Props(new Worker)) 
    Future.traverse(messages) { m => 
     implicit val timeout = Timeout(20 seconds) 
     println("Sending: " + m) 
     val result = worker ? m 
     result.asInstanceOf[Future[Result]] 
    } 
} 
+0

Die Variable 'actor' existiert nicht, meinst du' worker' hier? Ich bin mir nicht sicher, warum Sie tote Buchstaben sehen, es sei denn, Ihr Mitarbeiter antwortet nicht richtig, etwa weil er 'sender()' falsch verwendet. Vielleicht möchten Sie auch in "Future.sequence" schauen, um alle Ihre Ergebnisse als eine einzige "Zukunft" zu erhalten. Aber ich kann nicht mit Sicherheit sagen, ob das Problem behoben ist. – acjay

Antwort

0

Scheint, weil mein Timeout zu niedrig eingestellt war. Sollte groß genug gewesen sein, um alle Arbeiten abzudecken - zum Beispiel 40 Sekunden.

0

Die stumme Antwort lautet: Daten

Future.traverse(messages)(m => actor ? m).map(_.asInstanceOf[Result]) 

Aber es könnte besser sein, senden alle auf einmal:

class Worker extends Actor { 
    def receive = { 
    case Message(data) => 
     // Convert data into result 
     ... 
     sender ! result 
    case seq: Seq[Message] => 
     ... 
     sender ! results 

    } 
} 
+3

Sie können auch 'Future.traverse (Liste) (m => actor? M ...)' verwenden. 'traverse' ist analog zur Kombination von' map' und 'sequence'. –

+0

@PeterNeyens in der Tat, fühlen Sie sich frei zu bearbeiten oder antworte sich übrigens :) – ipoteka