sarah w
sarah w

Reputation: 3475

how to perform supervision in akka

I have two actors one is parent and one is child ,The child actor is responsible for fetching data from MongoDB against an given id and reply back the data to the calling actor which is a parent in my case ,Now i want to apply supervision in my child actor i know how to perform supervision strategy but how to do it in my code that's confusing me i am catching exception in my try/catch block so that every type of exception will be caught but then i am stuck on the point how to app,y supervision as i don't know exactly what exception my code will throw in future here is my code please help me ReadOnlyAdminQueryActor.scala(Patent Actor)

class ReadOnlyAdminQueryActor extends Actor{

val log = LoggerFactory.getLogger("controller")
     case ReadOnlyAdminReadByID(idList)=>
          var RetunedLists = new MutableList[ReadOnlyAdmin]()
          RetunedLists=  readById(idList)
          sender ! RetunedLists //return list of ReadOnlyAdmin objects to the calling actor (matched uuid results)
   def readById(idList:MutableList[Int]):MutableList[ReadOnlyAdmin]= {
    var connection=MongoFactory.getConnection
    var collection=MongoFactory.getCollection(connection, "readOnlyAdmin")

   var RetunedList = new MutableList[ReadOnlyAdmin]()

    var id:Int=0
    var email:String=""
    var SecondryEmail:Option[String]=None
    var FirstName:String=""
    var LastName:String=""
    var userStatus:String=""

  log.info("readOnlyAdmin query class data method readByID")

 for(Id<-idList){

    val q=QueryBuilder.start("_id").is(Id)

    val cursor=collection.find(q.get)
    var obj=new BasicDBObject

 try {
     while(cursor.hasNext)
     {
       obj=cursor.next().asInstanceOf[BasicDBObject]

       id=obj.getString("_id").toInt
       email=obj.getString("Email")
       SecondryEmail=Option(obj.getString("SecondryEmail"))
       FirstName=obj.getString("FirstName")
       LastName=obj.getString("LastName")
       userStatus=obj.getString("UserStatus")

       val readOnlyAdmin=new ReadOnlyAdmin(id,FirstName, LastName, email, SecondryEmail ,"",UserStatus.withName(userStatus))
       RetunedList+=readOnlyAdmin  //adding objects in a list


     }//end of while
   }//end of try
    catch
    {
      case e: Exception => log.error("printStackTrace"+e.printStackTrace)

    }
   finally{
     cursor.close()
     MongoFactory.closeConnection(connection)

   }
 }//end for loop

    RetunedList
 }
}

ReadOnlyAdminReadMongoActor.scala (Child Actor)

    class ReadOnlyAdminReadMongoActor extends Actor{
      val log = LoggerFactory.getLogger("controller")
      val ReadOnlyAdminQueryActor=context.actorOf(Props[ReadOnlyAdminQueryActor].withDispatcher("akka.actor.readOnlyAdminReadMongoActor-dispatcher"), name = "ReadOnlyAdminQueryActor")

    case ReadOnlyAdminReadFromMongoById(readOnlyAdmin,idList)=>
            var RetunedLists = new MutableList[ReadOnlyAdmin]()
            implicit val timeout = Timeout(10 seconds)//wait for 10 seconds 
override val supervisorStrategy: SupervisorStrategy = {
    OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 10 seconds) {
      case x: Exception => ???
    }
  }

             val future:Future[MutableList[ReadOnlyAdmin]] = ask(ReadOnlyAdminQueryActor,ReadOnlyAdminReadByID(idList)).mapTo[MutableList[ReadOnlyAdmin]] 
             future.onComplete { 
              case Success(result)=>
                RetunedLists=result
                      for(a<-RetunedLists)
                      {
                           log.info ("id is "+a.getUuid+"First name is "+a.getFirstName
                          +"Last name is "+a.getLastName+"Email is "+a.getEmail 
                          +"secondry email is "+a.getSecondryEmail+"user status is "+a.getUserStatus)
            }

             case Failure(e)=>
             log.error(" in failure")
             log.error("printStackTrace"+e.printStackTrace)
    }

object Test extends App{
 val system = ActorSystem("TestSystem")
val readOnlyAdmin= new ReadOnlyAdmin
var uuidsList = new MutableList[Int]()
uuidsList+=123
val ReadOnlyAdminReadMongoActor=system.actorOf(Props[ReadOnlyAdminReadMongoActor].withDispatcher("akka.actor.readOnlyAdminReadMongoActor-dispatcher"), name = "ReadOnlyAdminReadMongoActor")
ReadOnlyAdminReadMongoActor ! ReadOnlyAdminReadFromMongoById(readOnlyAdmin,uuidsList)       

}

how can i perform supervision in a correct way and how do i came to know which exception will be thrown in my child actor also Fortunately, Java libraries explicitly say what they're going to throw, and Scala libraries almost always throw very little or no even in IDE no information is shown when we hover the mouse on the code please help me thanks in advance

Upvotes: 1

Views: 118

Answers (1)

mattinbits
mattinbits

Reputation: 10428

The supervisor strategy belongs with the Parent, not the Child. The child should throw its exceptions and the parent determines how to handle the failure. In the code below, the Child actor will be restarted 3 times, then terminate:

class Parent extends Actor {

    override def preStart(): Unit = {
      self ! "Start Child"
    }

   def receive = {
     case "Start Child" => context.actorOf(Props[Child])
   }

  override def supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 3) {
    case ex: Throwable => Restart
  }
}

class Child extends Actor {

  override def preStart() = {
    self ! "Throw"
  }

  def receive = {
    case "Throw" => throw new Exception("Throwing")
  }
}

Upvotes: 1

Related Questions