Question

I am new to Scala and Akka but have a simple scenario... I am attempting to take a list of urls, sending each url as a message into a new actor that will make an http GET request. With only a list of 16 urls, I get about 40-65% successes with the others getting dead-letter "message was not delivered". However, if I put a Thread.sleep(50) before creating the actor(s), I don't get the dead-letter misses. Note: the HTTP Get is using a java class, not a scala class which may or may not be a factor. See code example below... I know Akka doesn't guarantee messages, but this success rate doesn't look right, I must be doing it wrong. Thanks for any pointers.

  def ParallelTest(urls: List[String]): String =   {
     val system = ActorSystem("HelloSystem")

     var cnt: Int = 0
     for (item <- urls){
       Thread.sleep(50)
       createActor(system, "helloactor" + cnt, item)
       cnt += 1
       /*
       historical example
       helloActor ! "hello"
       helloActor ! "hello"
       helloActor ! "Buenos dias"
       */
      }
     system.shutdown

     println("parallel done");
     "done"   
   }

  def createActor(actorSystem: ActorSystem, actorName: String, urlItem: String) = {
    val helloActor = actorSystem.actorOf(Props[HelloActor], name = actorName)
    helloActor ! UrlTransport(urlItem)
  }
Was it helpful?

Solution

You may want to consider doing something like this, having a manager for the actors to know when they are done.

class HelloManager(urls: List[String]) extends Actor {

    var completed = 0
    def remaining = urls.size - completed

    def receive: Receive = {
        case StartSystem => startRequests
        case RequestComplete => handleComplete

    }

    def startRequests(): Unit = {
        for ((url, i) <- urls.zipWithIndex) {
            val helloActor = context.actorOf(Props[HelloActor], name = s"helloActor$i")
            helloActor ! UrlTransport(url)
        }
    }  

    def handleComplete(): Unit = {
        completed += 1
        if (remaining == 0) 
            // do something like
            // context.stop(self)
    }
}

Then you just need the HelloActor to do a sender ! RequestComplete when it is done with its job.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top