0

I just started learning Scala and Akka and now I am trying to develop an application that uses ReactiveMongo framework to connect to a MongoDb server. The problem is that when I call system.shutdown() in the end of my App object, the process does not terminate and just hangs forever. I am now testing the case when there is no connection available, so my MongoDB server is not running. I have the following actor class for querying the database:

class MongoDb(val db: String, val nodes: Seq[String], val authentications: Seq[Authenticate] = Seq.empty, val nbChannelsPerNode: Int = 10) extends Actor with ActorLogging {
  def this(config: Config) = this(config.getString("db"), config.getStringList("nodes").asScala.toSeq,
    config.getList("authenticate").asScala.toSeq.map(c => {
      val l = c.unwrapped().asInstanceOf[java.util.HashMap[String, String]]; Authenticate(l.get("db"), l.get("user"), l.get("password"))
    }),
    config.getInt("nbChannelsPerNode"))

  implicit val ec = context.system.dispatcher
  val driver = new MongoDriver(context.system)
  val connection = driver.connection(nodes, authentications, nbChannelsPerNode)
  connection.monitor.ask(WaitForPrimary)(Timeout(30.seconds)).onFailure {
    case reason =>
      log.error("Waiting for MongoDB primary connection timed out: {}", reason)
      log.error("MongoDb actor kills itself as there is no connection available")
      self ! PoisonPill
  }

  val dbConnection = connection(db)
  val tasksCollection = dbConnection("tasks")
  val taskTargetsCollection = dbConnection("taskTargets")

  import Protocol._
  override def receive: Receive = {
    case GetPendingTask =>
      sender ! NoPendingTask
  }
}

My app class looks like this:

object HelloAkkaScala extends App with LazyLogging {
  import scala.concurrent.duration._

  // Create the 'helloakka' actor system
  val system = ActorSystem("helloakka")
  implicit val ec = system.dispatcher

  //val config = ConfigFactory.load(ConfigFactory.load.getString("my.helloakka.app.environment"))
  val config = ConfigFactory.load
  logger.info("Creating MongoDb actor")
  val db = system.actorOf(Props(new MongoDb(config.getConfig("my.helloakka.db.MongoDb"))))

  system.scheduler.scheduleOnce(Duration.create(60, TimeUnit.SECONDS), new Runnable() { def run() = {
    logger.info("Shutting down the system")
    system.shutdown()
    logger.info("System has been shut down!")
  }})
}

And the log output in my terminal looks like this:

[DEBUG] [08/07/2014 00:32:06.358] [run-main-0] [EventStream(akka://helloakka)] logger log1-Logging$DefaultLogger started
[DEBUG] [08/07/2014 00:32:06.358] [run-main-0] [EventStream(akka://helloakka)] Default Loggers started
00:32:06.443 INFO  [run-main-0] [HelloAkkaScala$] - Creating MongoDb actor
00:32:06.518 DEBUG [helloakka-akka.actor.default-dispatcher-3] [reactivemongo.core.actors.MonitorActor] - Actor[akka://helloakka/temp/$a] is waiting for a primary...  not available, warning as soon a primary is available.
00:32:06.595 DEBUG [helloakka-akka.actor.default-dispatcher-2] [reactivemongo.core.actors.MongoDBSystem] - Channel #-774976050 unavailable (ChannelClosed(-774976050)).
00:32:06.599 DEBUG [helloakka-akka.actor.default-dispatcher-2] [reactivemongo.core.actors.MongoDBSystem] - The entire node set is still unreachable, is there a network problem?
00:32:06.599 DEBUG [helloakka-akka.actor.default-dispatcher-2] [reactivemongo.core.actors.MongoDBSystem] - -774976050 is disconnected
00:32:08.573 DEBUG [helloakka-akka.actor.default-dispatcher-3] [reactivemongo.core.actors.MongoDBSystem] - ConnectAll Job running... Status: Node[localhost: Unknown (0/10 available connections), latency=0], auth=Set()
00:32:08.574 DEBUG [helloakka-akka.actor.default-dispatcher-3] [reactivemongo.core.actors.MongoDBSystem] - Channel #-73322193 unavailable (ChannelClosed(-73322193)).
00:32:08.575 DEBUG [helloakka-akka.actor.default-dispatcher-3] [reactivemongo.core.actors.MongoDBSystem] - The entire node set is still unreachable, is there a network problem?
00:32:08.575 DEBUG [helloakka-akka.actor.default-dispatcher-3] [reactivemongo.core.actors.MongoDBSystem] - -73322193 is disconnected
... (the last 3 messages repeated many times as per documentation the MongoDriver tries to re-connect with 2 seconds interval)
[ERROR] [08/07/2014 00:32:36.474] [helloakka-akka.actor.default-dispatcher-3] [akka://helloakka/user/$a] Waiting for MongoDB primary connection timed out: akka.pattern.AskTimeoutException: Ask timed out on [Actor[akka://helloakka/user/$c#1684233695]] after [30000 ms]
[ERROR] [08/07/2014 00:32:36.475] [helloakka-akka.actor.default-dispatcher-3] [akka://helloakka/user/$a] MongoDb actor kills itself as there is no connection available
... (the same 3 messages repeated again)
00:32:46.461 INFO  [helloakka-akka.actor.default-dispatcher-4] [HelloAkkaScala$] - Shutting down the system
00:32:46.461 INFO  [helloakka-akka.actor.default-dispatcher-4] [HelloAkkaScala$] - Awaiting system termination...
00:32:46.465 WARN  [helloakka-akka.actor.default-dispatcher-2] [reactivemongo.core.actors.MongoDBSystem] - MongoDBSystem Actor[akka://helloakka/user/$b#537715233] stopped.
00:32:46.465 DEBUG [helloakka-akka.actor.default-dispatcher-5] [reactivemongo.core.actors.MonitorActor] - Monitor Actor[akka://helloakka/user/$c#1684233695] stopped.
[DEBUG] [08/07/2014 00:32:46.468] [helloakka-akka.actor.default-dispatcher-2] [EventStream] shutting down: StandardOutLogger started
00:32:46.483 INFO  [helloakka-akka.actor.default-dispatcher-4] [HelloAkkaScala$] - System has been terminated!

And after that the process hands forever and does never terminate. What am I doing wrong?

Uniqus
  • 564
  • 1
  • 5
  • 21
  • As a temporary solution I added java.lang.Runtime.getRuntime.halt(1) after system.awaitTermination(...) call. Both System.exit(1) and java.lang.Runtime.getRuntime.exit(1) (which afaik are the same) did not solve the problem and the process still kept hanging. – Uniqus Aug 06 '14 at 22:03
  • Did you ever find a fix for this? I'm using 0.10.5.0 and still experiencing this problem. – Jason Nov 28 '14 at 16:03
  • Well, I don't know what happened, but it just works for me now. I used to call `java.lang.Runtime.getRuntime.halt(1)`, but at some point it became unnecessary. The version I'm currently using is 0.10.5.0.akka23 (with Scala 2.11.2). – Uniqus Dec 03 '14 at 13:23

1 Answers1

0

You aren't doing anything incorrect. This is a known issue.

https://github.com/ReactiveMongo/ReactiveMongo/issues/148

bearrito
  • 2,217
  • 1
  • 25
  • 36
  • Thank you for your answer. As far as I understand, netty is the former technology, used in the previous versions of akka. And the latest version uses it's own I/O stack based on spray.io. Is it true that reactivemongo still uses netty for networking? Or this bug has not been fixed since before akka v 2.2 (when it moved to spray.io)? – Uniqus Sep 11 '14 at 10:33
  • What branch of reactivemongo are you using? – bearrito Sep 11 '14 at 16:57
  • Well, I have "play2-reactivemongo" % "0.11.0-SNAPSHOT" in my build.sbt. And I indeed can see "netty:3.6.5.Final" in the "External Libraries" in my Idea project, although there is no direct dependency on it in my project's build.sbt. But I don't know how to find out what depends on it, and whether it is reactivemongo. – Uniqus Sep 11 '14 at 23:50
  • You can add the dependency graph plugin for sbt to your project. Using the command "dependency-graph" in the console will show you the dependency chains. More info on https://github.com/jrudolph/sbt-dependency-graph – tmbo Oct 24 '14 at 16:01