1

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

swaheed
  • 3,671
  • 10
  • 42
  • 103

1 Answers1

1

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")
  }
}
mattinbits
  • 10,370
  • 1
  • 26
  • 35
  • if we use the Restart strategy the child actor which processing the "Throw" message and exception occurred what will happend then the Message "Throw" will be sent to dead letters ? or this message will be destroyed ?or what will happen – swaheed Aug 19 '15 at 08:31
  • With the restart strategy, the ActorRef of the actor being restarted remains stable, but is backed by a new object of type `Child` each time. At each restart, a method called `postRestart` is called, which by default calls `preStart`. Therefore above, at every restart the message "Throw" is sent. These messages do not go to dead letters since they have been processed. It is the processing of them which causes the exception. – mattinbits Aug 19 '15 at 08:33
  • so in restart strategy the message which cause the exception remains there its not destroyed am i right ? – swaheed Aug 19 '15 at 08:45
  • No, that message is considered to have been processed, it is destroyed. but it doesn't go to dead letters. – mattinbits Aug 19 '15 at 08:47
  • but if we want to store that message ,because in some cases we don't want to lose that message we want it to process successfully in that case what can we do ? – swaheed Aug 19 '15 at 08:53
  • That message caused an exception, so to keep replaying it through would seem like a bad idea, since it may just keep creating the same exception. Akka has "At most once" delivery semantics, so if you need to guarantee that the message was received and processed, you need implement some kind of ACK-RETRY procedure. – mattinbits Aug 19 '15 at 08:55
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/87383/discussion-between-user3801239-and-mattinbits). – swaheed Aug 19 '15 at 12:48