Thanks Victor, Ryan for helping to clear up some fundamental understanding
of mine.
Can you please tell me why this works?
This ditches the Future.
The Driver does an Ask to MyBatchReader, which expects a future but
MyBatchReader returns a non-Future.
class MyDriver extends Actor{
implicit val timeout = Timeout( 1.second )
def receive = {
case _ =>
val f = (mybatchReader ? Read( "something" ) ).mapTo[Option[String]]
f.onComplete{
case Success( result:Option[String] ) =>
result match {
case Some( data:String ) =>
println( "Got result" )
case None =>
println( "Got no result" )
}
case Failure(e) =>
println( "Sendee future failed" )
e.printStackTrace()
}
}
}
class MyBatchReader extends Actor{
def receive = {
case Read(id) =>
val orig_sender = sender()
val x:String = someFunctionThatThrowsAnException()
// triggers parent supervisor
orig_sender ! x
println("Sent future to Sender" )
case _ => println( "Unknown" )
}
On Tuesday, December 9, 2014 2:25:50 PM UTC-5, Ryan Tanner wrote:
>
> As you can see, futures have their own form of error handling. The
> behavior you're seeing is exactly what's supposed to happen. Futures can
> be used completely independently of actors so if you want failed futures to
> trigger Akka's supervision, you'll need to do so yourself. In this case,
> if you really are just wrapped blocking functions up in futures within
> actors, I would ditch the futures entirely as they're only adding
> complexity.
>
> If you want an actor to restart if a failure it creates fails, you should
> send the failure message back to the actor itself and then let it re-throw
> the exception.
>
>
>
> On Tuesday, December 9, 2014 12:11:53 PM UTC-7, David wrote:
>>
>> Question in a nutshell:
>> My Akka Actor creates a Future using the macro Future{someBlockingCall}
>> within it's receive method.
>> Inside someBlockingCall, I throw an exception. This does not trigger a
>> supervisor in the parent. How can get the future to trigger a parent
>> supervisor restart?
>>
>>
>> In MyBatchReader, I have tested two places to throw exceptions:
>>
>> class MyBatchReader extends Actor{
>> def receive = {
>> case Read(id) =>
>> val orig_sender = sender()
>>
>> //val s = someFunctionThatThrowsAnException()
>> // Does trigger parent supervisor
>>
>> val f:Future[Option[String]] = Future{
>>
>> someFunctionThatThrowsAnException() //
>> Does NOT trigger parent supervisor
>>
>> }
>>
>> f pipeTo orig_sender
>> //orig_sender ! s
>>
>> println("Sent future to Sender" )
>>
>> case _ => println( "Unknown" )
>> }
>>
>>
>>
>> The caller of MyBatchReaderActor:
>>
>> class MyDriver extends Actor{
>>
>> implicit val timeout = Timeout( 1.second )
>>
>> def receive = {
>> case _ =>
>> val f = (mybatchReader ? Read( "something" )
>> ).mapTo[Option[String]]
>> f.onComplete{
>> case Success( result:Option[String] ) =>
>> result match {
>> case Some( data:String ) =>
>> println( "Got result" )
>> case None =>
>> println( "Got no result" )
>> }
>>
>> case Failure(e) =>
>> println( "Sendee future failed" )
>> e.printStackTrace()
>>
>> }
>> }
>> }
>>
>>
>>
>> So, MyDriver does a "?" on MyBatchReader which then itself creates a
>> Future using Future{} macro.
>>
>> Is this incorrect code?
>>
>> In the above code, what I am seeing is the exception thrown, the future
>> completing with FAILURE( "Sendee future failed" ), but the parent *NOT*
>> executing a restart.
>>
>> If I change MyBatchReader to be (removing the macro creation of another
>> future):
>>
>> class MyBatchReader extends Actor{
>> def receive = {
>> case Read(id) =>
>> val orig_sender = sender()
>> val x:String = someFunctionThatThrowsAnException()
>> // triggers parent supervisor
>> orig_sender ! x
>> println("Sent future to Sender" )
>> case _ => println( "Unknown" )
>> }
>>
>>
>> this works (trigger parent supervision) BUT I don't see how this can work
>> since the sender is expecting a future back but MyBatchReader is returning
>> a string.
>> Or does the ask "?" in MyDriver automatically create a future? (Even when
>> I use ! instead of pipeTo in MyBatchReader, MyDriver still does the
>> onComplete callback!)
>>
>>
>> In general, when writing receive methods in actors, is it correct to say
>> that I should never do this?
>>
>> class AnActor extends Actor{
>>
>> def receive = {
>> case Read(id) =>
>> val orig_sender = sender()
>>
>>
>> // Exception thrown in "funcThrows()"
>> // f completes with FAILURE
>> // Won't trigger parent supervisor
>> val f:Future = Future{ funcThrows() } // When funcThrows throws,
>> I want to cause AnActor to restart
>>
>> f pipeTo orig_sender
>> println("Sent future to Sender" )
>> case _ => println( "Unknown" )
>>
>> }
>>
>> thanks in advance,
>>
>> David
>>
>
--
>>>>>>>>>> Read the docs: http://akka.io/docs/
>>>>>>>>>> Check the FAQ:
>>>>>>>>>> http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
---
You received this message because you are subscribed to the Google Groups "Akka
User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.