Weird try/catch behaviour with Scala + Akka - scala

I'm trying to use Akka to implement a TCP server for a custom application protocol. I'm trying to follow the example given here: http://doc.akka.io/docs/akka/2.0/scala/io.html to do non-blocking IO inside a for...yield loop.
I find that when I throw an exception from inside the yield block, I can't catch it from outside the block. I think I've got a fundamental misunderstanding of how Akka or Scala is working here and I'd appreciate any tips.
I've boiled down the code to this:
import akka.actor._
import java.net.InetSocketAddress
class EchoServer(port: Int) extends Actor {
val state = IO.IterateeRef.Map.async[IO.Handle]()(context.dispatcher)
override def preStart {
IOManager(context.system) listen new InetSocketAddress(port)
}
def receive = {
case IO.NewClient(server) =>
val socket = server.accept()
state(socket) flatMap (_ => EchoServer.processRequest(socket))
case IO.Read(socket, bytes) =>
state(socket)(IO.Chunk(bytes))
case IO.Closed(socket, cause) =>
state(socket)(IO.EOF(None))
state -= socket
}
}
object EchoServer extends App
{
def processRequest(socket: IO.SocketHandle): IO.Iteratee[Unit] =
{
println( "In process request")
try {
for {
bs <- IO take 1
} yield {
println("I'll get here")
throw new Exception("Hey-o!")
println("But not here ... as expected")
}
} catch {
case e: Exception => println("And not here ... wtf?"); IO.Done() // NEVER GETS HERE
}
}
ActorSystem().actorOf(Props(new EchoServer(8080)))
}
Maybe more convenient to follow the gist here: https://gist.github.com/2296554
Can anybody explain why control does not reach my catch block in this situation?
I noticed that if I turn on debug logging in Akka, I see this message in the output:
[DEBUG] [04/03/2012 22:42:25.106] [EchoServerActorSystem-akka.actor.default-dispatcher-1] [Future] Hey-o!
So I guess the exception is getting handled by the Akka dispatcher? Can anybody explain how that's possible?

The point of non-blocking IO is of course that there is no guarantee when and where it is executed. Remember that one can write the for comprehension as
(IO take 1).map(bs => {
println("I'll get here"); throw // ...
}
What does this code do? IO take 1 returns some non-blocking Future-like thing, which is then appended a transforming function through the map method. I.e. whenever (and wherever) IO take 1 is ready, it will apply the map on the result.
All of this happens in some other thread (or using some other way of implementing the non-blocking semantics), so there is no way for the try–catch to react on any Exceptions being thrown. Nor would the bs => println(…) … method know of your exception handling. All it knows it that it should transform some input bs and have a result when it’s finished.
The lesson to be learned: When using non-blocking code avoid side-effects. Especially so, if the side effects are being used to change the flow of execution.
In order to actually catch the exception, I think you’ll have to structure it as follows (untested; see API):
def processRequest(socket: IO.SocketHandle): IO.Iteratee[Unit] =
{
println( "In process request")
(
for {
bs <- IO take 1
} yield {
println("I'll get here")
throw new Exception("Hey-o!")
println("But not here ... as expected")
}
) recover {
case e: Exception => println("And here ...?"); IO.Done()
}
}

Related

scala: playframework controller action execution sequence with future

I am having problem with my play-framework API server. I need to have some processing running in the background that is returning a Future with the result and then write the result as response. However, the request thread goes all out and return before my Future completes. Here is the code...
def requestAction(): Action[AnyContent] = Action.async { implicit request =>
var fResult: Future[String] = Future { "initial value" }
try {
fResult = doSomethingAsyncAndGetResponseString(); // return "great, everything is done"
}
catch {
case t: Throwable {
fResult = Future { "failed" }
}
}
// done, return response, but the problem is, this is executed first because doSomethingAsyncAndGetResponseString() is still executing and returns later
fResult.map( res => {
// problem here, because I get "initial value" which is not what I want
Ok(res)
}
}
Is there a way to get "great, everything is done" or "failed" without Async.await ? I have been using this format all over in my API server, but today it broke because in a new API that I write, the doSomethingAsyncAndGetResponseString is a bit longer. I didn't expect that, so something must be wrong with how I understand the structure.
Thanks in advance!
You are trying to write Java like code using Scala.
You are doing it wrong. Read about Futures and How to use them.
Here is the tutorial
Futures can be composed using map and flatMap constructs. recover and recoverWith will give the user access to exception happened in the computation pipeline
You have to do something like this, given below
def requestAction(): Action[AnyContent] = Action.async { implicit request =>
Future { "initial value" }.flatMap { _ =>
doSomethingAsyncAndGetResponseString() // returns Future
}.map { res =>
Ok(res)
}.recover { case th =>
Ok(th.getMessage)
}
}
Handling exceptions and recovering from exceptions
Exception handling is inbuilt into Future.
recover gives access to exception and also helps the user to provide the alternative success value in case of exception.
recoverWith gives access to an exception and also helps the user to provide/chain alternative Future computation which can succeed or fail.
Future {
throw new Exception("foo exception")
}.recover {
case th => println(s"msg: ${th.getMessage}")
}

How to return early in a pattern match of akka actor receive

Tried googling variations on this trivial question but didn't get an answer...
Basically I have a pattern match in my receive method.
In some cases I want to break early from the receive handling
override def receive = {
case blah => {
... preflight code
if (preflight failed) {
sender() ! errorMSG
"break" or "return" here // get error "method receive has a return statement ; needs result type -
// I tried adding Unit to the receive and return statements
}
... more code
....
if (something happened) {
sender() ! anotherErrorMSG
"break" or "return" here
}
...
}
case foo => {...}
case bar => {...}
} // end receive
See this discussion of return's semantics and remember that receive returns a PartialFunction[Any, Unit] which is then evaluated after receive has returned. In short, there's no way to return early.
Ömer Erden's solution of throwing an exception and using actor supervision works (indeed, exception throwing with all of its overhead is basically the only way to reliably end a computation early), but if you need any state to carry over from message to message, you'll need Akka persistence.
If you don't want to nest if-elses as in chunjef's solution, you can use context.become and stash to create some spaghetti-ish code.
But the best solution may be to have the things that might fail be their own functions with Either result types. Note that the Either API in scala 2.12 is quite a bit nicer than in previous versions.
import scala.util.{ Either, Left, Right }
type ErrorMsg = ...
type PreflightSuccess = ... // contains anything created in preflight that you need later
type MoreCodeSuccess = ... // contains anything created in preflight or morecode that you need later
def preflight(...): Either[ErrorMsg, PreFlightSuccess] = {
... // preflight
if (preflight failed)
Left(errorMsg)
else
Right(...) // create a PreflightSuccess
}
def moreCode1(pfs: PreFlightSuccess): Either[ErrorMsg, MoreCodeSuccess] = {
... // more code
if (something happened)
Left(anotherErrorMSG)
else
Right(...) // create a MoreCodeSuccess
}
def moreCode2(mcs: MoreCodeSuccess): Either[ErrorMsg, Any] = {
... // more code, presumably never fails
Right(...)
}
override def receive = {
case blah =>
val pf = preflight(...)
val result = pf.map(morecode1).joinRight.map(moreCode2).joinRight // only calls morecode1 if preflight succeeded, and only calls morecode2 if preflight and morecode1 succeeded
result.fold(
{ errorMsg => sender ! errorMsg },
()
)
case foo => ...
case bar => ...
}
Whether this is preferable to nested if-else's is a question of taste...
This may not be your question's exact answer but in your case adding supervisor actor would be the better solution. In Akka Supervision model convince you to handle exceptions on supervisor actor instead of sending error messages back to the sender.
This approach brings you a fault-tolerant model and also you can throw exception at any line you want(which solves your current problem), your supervisor actor will handle the throwable with restarting, resuming or stopping the child actor.
please check the link

Am I safely mutating in my akka actors or is this not thread safe?

I am a little confused if I am safely mutating my mutable maps/queue inside of my actor.
Can someone tell me if this code is thread-safe and correct?
class SomeActor extends Actor {
val userQ = mutable.Queue.empty[User]
val tranQ = mutable.Map.empty[Int, Transaction]
def receive = {
case Blank1 =>
if(userQ.isEmpty)
userQ ++= getNewUsers()
case Blank2 =>
val companyProfile = for {
company <- api.getCompany() // Future[Company]
location <- api.getLoc() // Future[Location]
} yield CompanyProfile(company, location)
companyProfile.map { cp =>
tranQ += cp.id -> cp.transaction // tranQ mutatated here
}
}
}
Since I am mutating the tranQ with futures, is this safe?
It is my understanding that each actor message is handled in a serial fashion, so although maybe frowned upon I can use mutable state like this.
I am just confused if using it inside of a future call like tranQ is safe or not.
No, your code is not safe.
While an actor processes one message at a time, you will lose this guarantee as soon as Futures are involed. At that point, the code inside the Future is executed on a (potentially) different thread and the next message might be handled by the actor.
A typical pattern to work around this issue is to send a message with the result of the Future using the pipeTo pattern, like so:
import akka.pattern.pipe
def receive: Receive {
case MyMsg =>
myFutureOperation()
.map(res => MyMsg2(res))
.pipeTo(self)
case MyMsg2(res) =>
// do mutation now
}
More information about using Futures can be found in akka's documentation: http://doc.akka.io/docs/akka/2.5/scala/futures.html

Quitting of actor without error message

This is a problem from the chat I'm developing.
There is a main/gui object with the main method, an Actor sender, that sends the messages and a empfänger, that receives them.
The Problem is to make the empfänger use a function of the main/gui object to show the incoming messages. Because it didn't work, I simplified it, but I still didn't get the problem.
May anyone tell my why this returns nothing at the terminal?
What am I doing wrong?
import scala.actors._
object main_object {
def infoterm(msg: String) = {
println(msg)
}
def main(args: Array[String]) = {
println("hallo")
empfänger ! "foo"
}
}
object empfänger extends Actor{
var port = 50042
var name = "local"
var continuevar = true
def foo(in: String) = {
println("foo-empfänger" + in)
}
def act() {
println("ydfjskj")
test2.infoterm("tut")
println("Empfänger gestartet")
while(continuevar) {
react {
case msg:String => {
println("empfänger" + msg)
test2.infoterm(msg)
foo("empfänger" + msg)
}
}
}
}
}
Thanks for you help, but I still don't get on.
I modified like you told me but it's still not working.
Only by defining the Actor empfänger the whole program stops working, like this:
import scala.actors._
object test2 {
def infoterm(msg: String) = {
println(msg)
}
def main(args: Array[String]) = {
println("hallo")
}
}
object empfänger extends Actor{
def act() {
// test2.infoterm("tut")
// println("Empfänger gestartet")
loop {
react {
case msg:String => {
if(msg == "Stop") exit()
else {
println("empfänger" + msg)
// test2.infoterm(msg)
}
}
}
}
}
}
What am I doing wrong?
There are two ways from within an actor of looping upon receiving events:
while-receive
loop-react
You are using a mixture of the two (i.e. while-react). This simply cannot work for the following reasons:
receive
Receive blocks the current thread of execution waiting for a message to process. It can be used in a while-loop; although you should rarely use this as it ties an actor to a single thread - i.e. it is not scalable because you use 1 thread per actor.
react
Notice that the signature of the react method says that its return type is Nothing. This means that the method cannot terminate normally; it must either never return or throw an exception. In fact the latter happens; it uses exceptions as a flow-control mechanism, which only works when you use react inside loop (assuming you want to continually handle events). So your act method should look like this:
def act() {
loop {
react {
case msg: String =>
}
}
}
It's well worth a look at the actor source code to see how the exception flow control works as it is a thing of beauty.
Error Messages: Linking actors
This is something I have struggled with for the actor framework. If an actor's reactions throw an exception, the actor exits and it's quite common to have no record of this is sys-out or sys-err. It can be extremely frustrating.
I strongly recommend linking canary actors to each system actor to listen for exits as follows:
def act() {
import Actor._
self link actor {
case Exit(from, msg) => /* your logging here */
}
loop { ...
}
}
}
However, this does not work in your case (again, extremely frustrating) because your whole act method throws an exception.
You're using a while loop inside the act method. The actor works asynchronously and gets activated, when it receives a message. Use loop {} instead of while and it should work. To stop an actor you have to send it a message like 'stop and react to it in your act method with exit.
Actors are not automagically started, that would be a bad thing. You have to explicitly call the 'start' method, ie, in your main() empänger.start()

Unable to obtain Akka Future Value Akka 1.3-RC2

I am new to Akka and making several test files to practice Akka concepts. The following test seemed simple enough, but for whatever reason I am unable to obtain the value of the future if I receive the future from an Actor. I based all my assumptions on the few examples from the akka documentation ( http://akka.io/docs/akka/1.3-RC2/scala/futures.html#futures-scala ) For example:
This works like a wizard:
val f = Future{ 1 + 4 }
f onComplete
{
_.value.get.fold(
v => throw new Exception("My Exception"),
println(_)
)
}
This does not:
class FutureDemo extends Actor
{
def receive =
{
case (a: Int, b: Int) =>
a + b
}
}
val fa1 = actorOf[FutureDemo].start()
val future = fa1 ? (1, 2)
future onComplete
{
_.value.get.fold(
v => throw new Exception("My Exception"),
println(_)
)
}
I was very pleased to know I was the only one that has ever had this issue due to the extreme simplicity of futures (lucky me). Would anyone assist in opening my eyes to the violently obvious issue?
I should note that I had tried to process both inside another actor, and in a simple main method. Each of which failed in the same awesome way which included no notification whatsoever. If the onComplete is replaced with a simple println(future.get) I eventually get a timeout exception (Exception in thread "main" akka.dispatch.FutureTimeoutException: Futures timed out after [4996] milliseconds). I should also note that I did attempt to try with the 1.1 and 1.2 released versions of akka as well.
Thanks!
It is indeed but one tiny detail you are missing: your actor does not reply! May I suggest the following:
class FutureDemo extends Actor {
def receive = {
case (a: Int, b: Int) => self.reply(a + b)
}
}