'Deadlock' in scala - scala

I want to rewrite in scala the example from Sun's tutorial about concurrency in java. The original code is here: http://java.sun.com/docs/books/tutorial/essential/concurrency/deadlock.html
This code is incorrect. It freezes at where the comment indicates. Could anyone correct this? Thanks in advance.
import scala.actors.Actor
class Person(val name: String) extends Actor {
def bow(other: Person) {
other ! Bow(this)
}
private def bowBack(backTo: Person) {
println(this.name + " is bowing back to " + backTo.name)
backTo ! Bowed(this)
}
def act() {
while (true) {
receive {
case Bow(p) =>
println(this.name + " is bowing to " + p.name)
p ! BowBack(this)
println(" wating for bowing back...")
var received = false
while (true && received == false) {
receive { //blocked here
case Bowed(other) if p == other =>
println(" ... " + this.name + " has bowed to " + other.name)
received == true
}
}
println(this.name + " has bowed to " + p.name)
case BowBack(p) =>
println(this.name + " is bowing back to " + p.name)
p ! Bowed(this)
case "EXIT" => return
case x => println(x)
}
}
}
}
abstract case class Action()
case class Bow(person: Person) extends Action
case class BowBack(person: Person) extends Action
case class Bowed(person: Person) extends Action
object BowTest extends Application {
val a = new Person("Alphone")
val g = new Person("Gaston")
a.start()
g.start()
a ! Bow(g)
//g.bow(a)
a ! "EXIT"
g ! "EXIT"
}

The first mistake is that you wrote result == true. This should be changed to result = true
You should delete the true value from the while condition. It has no influence.
In the BowTest object you should add after the g.bow(a) instruction Thread.sleep(1000) to give actors enough time to respond to the messages.
In this way your code should work. But still it has a deadlock. If you will change g.bow(a) in a.bow(g) the execution will freeze. This is caused by the receive block. Each actor is waiting for the Bowed message, but they cannot respond to the BowBack message.
When you are responding to a message, you should use receive block only if you are sure that the actor will get the specified messages. But usually this is not a good practice in designing actors. They should not block. The main purpose of an actor is to respond as fast as possible to a message. If you have to do a big task you should use futures, but in this case is not required.
A solution will be to retain the persons which are bowed in a list. When the actor have to bow a person it adds it in the list. When the actor is bowed by a person which is in the list, it removes that person from the list.
while (true) {
react {
case Bow(p) =>
println(this.name + " is bowing to " + p.name)
addPersonToBowList(p)
p ! BowBack(this)
case Bowed(other) if isPersonInBowList(other) =>
println(" ... " + this.name + " has bowed to " + other.name)
removePersonFromBowList(other)
case BowBack(p) =>
println(this.name + " is bowing back to " + p.name)
p ! Bowed(this)
case "EXIT" => exit()
case x => println(x)
}
}

Not deadlock, just a plain ol' bug, I think. Two lines under your comment:
received == true
This should be = instead of ==. I've not looked in depth (this sprung out at me) but it looks like this would fix your issue.

Related

akka- how to ensure all responses of dynamic number of actors are returned to parent actor?

I need to create variable number of actors each time my program starts and then must ensure all responses are return after a period of time. This
link gives a good idea for fixed number of actors but what about dynamic number?
This is my code that creates actor and passes messages to them:
ruleList = ...
val childActorList: Iterable[ActorRef] = ruleList.map(ruleItem =>
context.actorOf(DbActor.props(ruleItem.parameter1, ruleItem.parameter2)))
implicit val timeout = Timeout(10.second)
childActorList.foreach(childActor =>
childActor ? (tempTableName, lastDate)
)
Updated-1
According to #Raman Mishra guides , I updated my code as bellow, this is the code in parent actor:
override val supervisorStrategy: SupervisorStrategy = {
OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 10 seconds) {
case exp: SQLException => //Resume;
throw exp
case exp:AskTimeoutException => throw exp
case other: Exception => throw other
}
}
override def receive: Receive = {
case Start(tempTableName, lastDate) => {
implicit val timeout = Timeout(10.second)
ruleList.foreach { ruleItem =>
val childActor = context.actorOf(DbActor.props(ruleItem._1, query = ruleItem._2))
ask(childActor, (tempTableName, lastDate)).mapTo[Seq[Int]]
onComplete {
lastDate)).mapTo[Seq[Int]] onComplete {
case util.Success(res) => println("done" + res + ruleItem._2)
case util.Failure(exp: AskTimeoutException) => println("Failed query:" + ruleItem._2); throw exp
case other => println(other)
}
}
And in child actor:
case (brokerTableName, lastDate) => {
Logger("Started query by actor" + self.path.name + ':' +
val repo = new Db()
val res = repo.getAggResult(query = (brokerTableName, lastDate))
val resWrapper = res match {
case elem: Future[Any] => elem
case elem:Any => Future(elem)
}
resWrapper pipeTo self
}
case res:List[Map[Any, Any]] => {
// here final result is send to parent actor
repo.insertAggresults(res, aggTableName) pipeTo context.parent
}
Now, whenever I run main app, first, parent actor starts and create child actors and send messages to them using ask method. Child actors do their tasks but the problem here is child actors response never returns back to parent actor and in every run of app, AskTimeoutException occurs. I doubt if the use of onComplete method is correct or not. Any help will be appreciated.
"Updated-2"
I found out the problem is in using context.parent instead of sender(). Also, when I pipe to sender, first part of my result, and the sender ask for second part, the problem is resolved but I don't know what happens here, why Can't I pipe to self and return the final result to parent?
This is the last code:
In parent actor:
override def receive: Receive = {
case Start(tempTableName, lastDate) => {
println("started: called by remote actor")
implicit val timeout = Timeout(5 second)
ruleList.foreach { ruleItem =>
val childActor = context.actorOf(DbActor.props(ruleItem._1, query = ruleItem._2))
ask(childActor, Broker(tempTableName, lastDate)) onComplete {
// (childActor ? Broker(tempTableName, lastDate)).mapTo[Seq[Int]] onComplete {
case util.Success(res: List[Map[Any, Any]]) => (childActor ? res) onComplete {
case util.Success(res: Seq[Any]) => println("Successfull- Num,ber of documents:" + res.length + " " + ruleItem._2)
case util.Failure(exp: AskTimeoutException) => println("Failed for writing - query:" + ruleItem._2); throw exp
}
case util.Failure(exp: AskTimeoutException) => println("Failed for reading - query :" + ruleItem._2); throw exp
case other => println(other)
}
}
}
}
In child actor:
case (brokerTableName, lastDate) => {
Logger("Started query by actor" + self.path.name + ':' +
val repo = new Db()
val res = repo.getAggResult(query = (brokerTableName, lastDate))
val resWrapper = res match {
case elem: Future[Any] => elem
case elem:Any => Future(elem)
}
resWrapper pipeTo sender()
}
case res:List[Map[Any, Any]] => {
// here final result is send to parent actor
repo.insertAggresults(res, aggTableName) pipeTo sender()
}
The reason that replying to sender() works where replying to context.parent does not is that ask creates an temporary actor to handle the response. You need to reply to this temporary actor: the sender (which is different from the parent).
Also it's not clear whether the getAggResult method is blocking. If so this will not help (see here).

Time outs and crash when using actors from a mapping function

I want to do something like this:
For every item in the collection, ask an actor and block while waiting for the response for some timeout interval, if the time out exception is thrown, I want to move on to the next item.
Here's the code pattern:
implicit val timeout: akka.util.Timeout = 3 seconds
collection.foreach { item =>
val future = (actor ? Request(msg = item)).mapTo[Response]
future.onComplete {
case Failure(ex) => // log ex
case Success(resp) => // use resp
}
Await.result(future, 3 seconds)
}
The actor is itself calling other actors which might take longer than my 3 second time out.
This doesn't work as expected: after the first item times out, the whole thing crashes and stops. There are some dead letter notifications, I suppose that's because when the actors that my actor is calling finish, the original sender is invalid (it took more than 3 seconds). So my question is how do I tell it to just forget the time out item and continue with the rest as if nothing happened?
#stefanobaghino is right. See here, as written in documentation if a future contains an exception then Await.result throws is so that it can be handled properly.
Here you are matching Failure case of future but you are not recovering from it. A better approach would be like following -
collection.foreach { item =>
val future = (actor ? Request(msg = item)).mapTo[Response]
future.recover {
case ex: Exception =>
// log ex
Response(ex.message) // some other object of type Response
}
val response = Await.result(future, 3 seconds)
// use response here
}
After reading answer by #Dimitri I tried logging timestamps in milliseconds to see where it was causing lag in whole process and i found rather strange behavior. I observed that whenever there were dead-letters there was huge lag in even starting processing of next message to actor. Not sure why this is happening. Below is the code i tried to check it -
package com.lightbend.akka.sample
import akka.actor.{ Actor, ActorLogging, ActorRef, ActorSystem, Props }
import akka.pattern.{ ask, pipe, AskTimeoutException }
import scala.concurrent.Await
import scala.concurrent.duration._
import scala.io.StdIn
import scala.util.{ Try, Success, Failure }
import scala.concurrent.ExecutionContext.Implicits.global
import java.util.concurrent.TimeoutException
object AkkaQuickStart {
class NumberActor extends Actor {
override def receive: Receive = {
case (num: Int, startAt: Long) =>
println("B " + num.toString + " : " + System.currentTimeMillis().toString + " : " + (System.currentTimeMillis() - startAt).toString)
Thread.sleep(500 * num)
sender() ! "OK"
}
}
def main(args: Array[String]): Unit = {
implicit val timeout: akka.util.Timeout = 1 seconds
val numActor = ActorSystem("system").actorOf(Props(new NumberActor()))
val range = (1 to 5) ++ (4 to 1 by -1)
println(range)
def lag(implicit startAt: Long): String = (System.currentTimeMillis() - startAt).toString
range.map { r =>
implicit val startAt = System.currentTimeMillis()
println("A " + r.toString + " : " + System.currentTimeMillis().toString + " : " + lag)
val future = (numActor ? (r, startAt))
.recover {
case ex: AskTimeoutException =>
println("E " + r.toString + " : " + System.currentTimeMillis().toString + " : " + lag)
"Ask timeout"
}
.mapTo[String]
future.onComplete{
case Success(reply) =>
println("C " + r.toString + " : " + System.currentTimeMillis().toString + " : " + lag + " : success " + reply)
case Failure(reply) =>
println("C " + r.toString + " : " + System.currentTimeMillis().toString + " : " + lag + " : failure")
}
Try(Await.result(future, 1 seconds)) match {
case Success(reply) =>
println("D " + r.toString + " : " + System.currentTimeMillis().toString + " : " + lag + " : " + reply)
case Failure(ex) =>
println("D " + r.toString + " : " + System.currentTimeMillis().toString + " : " + lag + " : Await timeout ")
}
}
}
}
I tried different combinations of Ask timeout and Await timeout and found following lags in starting processing of actor message sent at the end of iteration -
Ask timeout = 1 Await Timeout = 1 => 3000 - 4500 ms causes dead-letters
Ask timeout = 1 Await Timeout = 3 => 3000 - 4500 ms causes dead-letters
Ask timeout = 3 Await Timeout = 1 => 3000 - 4500 ms causes dead-letters
Ask timeout = 3 Await timeout = 3 => 0 - 500 ms does not cause dead-letters
I am not sure but a guess is that dispatcher takes time in handling dead-letters and thus can not start processing messages of our Actor. May be some more experienced can explain it.
#stefanobaghino #Tarun Thanks for your help, I think I got it now.
So the thing is there are 2 timeouts that can cause an exception:
The Ask (?) timeout throws akka.pattern.AskTimeoutException if we have to wait longer than the actor takes to respond.
The Await.result throws java.util.concurrent.TimeoutException if we don't wait long enough for the future to finish.
Both of these can cause the whole thing to crash. For the first one, as you mentioned, we can add recover to return some default value. For the second one, we also should catch and handle the exception.
You can see different behaviours when changing the two timeouts and removing the recover/Try in the following example:
object Example {
class NumberActor extends Actor {
override def receive: Receive = {
case num: Int =>
Thread.sleep(250 * num)
sender() ! "OK"
}
}
def main(): Unit = {
implicit val timeout: akka.util.Timeout = 1 seconds
val numActor = ActorSystem("system").actorOf(Props(new NumberActor()))
val range = (1 to 5) ++ (4 to 1 by -1)
println(range)
range.map { r =>
val future = (numActor ? r)
.recover { case ex: TimeoutException => "FAIL" }
.mapTo[String]
Try(Await.result(future, 1 seconds)) match {
case Success(reply) => println(reply)
case Failure(ex) => println(ex)
}
}
}
}

Scala Akka Play, Future doesn't return

I'm using Scala 2.10, Akka 2.1 and Play 2.1. When I send an http request to my backend, I ask one actor to compute something. The idea is to return the result of the calculation if it returns before a timeout, otherwise a different string. See code below.
val futureInt: Future[Int] = ask(testActor, Calculate(number.toInt)).mapTo[Int]
val timeoutFuture = play.api.libs.concurrent.Promise.timeout("Oops", 2.seconds)
Async {
Future.firstCompletedOf(Seq(futureInt, timeoutFuture)).map {
case i: Int => Ok("Got result " + i)
case t: String => Ok("timeout expired")
}
}
The actor is as follows:
class TestActor() extends Actor {
def receive = {
case Calculate(tonumber: Int) =>
for (a <- 1 to tonumber) {
val c: Double = scala.math.pow(a, 2)
println("a: " + a + ", c: " + c)
}
12345 // hardcoded value to return when the calculation finishes
case _ =>
println("bah")
}
}
My problem is that even if the actor finishes before the timeout, nothing is "returned" by the Future and so the timeout always expires. What am I doing wrong? Thanks a lot.
From http://doc.akka.io/docs/akka/snapshot/scala/actors.html
Using ask will send a message to the receiving Actor as with tell, and the receiving actor must reply with sender ! reply in order to complete the returned Future with a value.
and
Warning
To complete the future with an exception you need send a Failure message to the sender. This is not done automatically when an actor throws an exception while processing a message.
So instead of "returning" like you would in a usual scala function, do something along the lines of
def receive = {
case Calculate(tonumber: Int) =>
...
sender ! 12345
case _ =>
sender ! akka.actor.Status.Failure(new InvalidArgumentException)
}

Scala-redis subscribes to * but receives zero messages

Integrating redis with my Scala application using Akka but for some reason it does not receive any messages. I can confirm that redis does have a ton of traffic on its side by opening the redis-cli on the command line.
After a pSubscribe it receives: subscribed to * and count = 1
My guess is that it might be related to the way Akka is set up to receive callbacks. I had to strip out Scala Actors in the scala-redis lib and replace them with Akka actors due to some conflicts.
Here's the code:
The Subscriber Actor
class Subscriber(client: RedisClient) extends Actor {
var callback: PubSubMessage => Any = { m => }
def receive: Receive = {
case Subscribe(channels) =>
client.subscribe(channels.head, channels.tail: _*)(callback)
case pSubscribe(channels) =>
client.pSubscribe(channels.head, channels.tail: _*)(callback)
case pSubscribeAll(channels) =>
Logger.info("Subscribing to all channels")
client.pSubscribe(channels.head, channels.tail: _*)(callback)
case Register(cb) =>
Logger.info("Callback is registered")
callback = cb
case Unsubscribe(channels) =>
client.unsubscribe(channels.head, channels.tail: _*)
case UnsubscribeAll =>
client.unsubscribe
}
}
Initializing the Subscriber
class RelaySub extends Actor {
// important config values
val system = ActorSystem("pubsub")
val conf = play.api.Play.current.configuration
val relayPubHost = conf.getString("relays.redis.host").get
val relayPubPort = conf.getInt("relays.redis.port").get
val rs = new RedisClient(relayPubHost, relayPubPort)
val s = system.actorOf(Props(new Subscriber(rs)))
s ! Register(callback)
s ! pSubscribeAll(Array("*"))
Logger.info("Engine Relay Subscriber has started up")
def receive: Receive = {
case Register(callback) =>
}
def callback(pubsub: PubSubMessage) = pubsub match {
case S(channel, no) => Logger.info("subscribed to " + channel + " and count = " + no)
case U(channel, no) => Logger.info("unsubscribed from " + channel + " and count = " + no)
case M(channel, msg) =>
msg match {
// exit will unsubscribe from all channels and stop subscription service
case "exit" =>
Logger.info("unsubscribe all ... no handler yet ;)")
// message "+x" will subscribe to channel x
case x if x startsWith "+" =>
Logger.info("subscribe to ... no handler yet ;)")
// message "-x" will unsubscribe from channel x
case x if x startsWith "-" =>
Logger.info("unsubscribe from ... no handler yet ;)")
// other message receive
case x =>
Logger.info("Engine: received redis message")
val channelVars = channel.split(".").toArray[String]
if(channelVars(0)!=Engine.instanceID)
channelVars(1) match {
case "relay" =>
EngineSyncLocal.constructRelay(channel, msg)
case _ =>
Logger.error("Engine: received unknown redis message")
}
}
}
}
Thanks for your help!
I found the problem. It appears to be a bug in the scala-redis client.
I added some logging in the consumer class and began receiving Engine: weird message errors which means that it doesn't recognize the incoming traffic. I'll contact the author and put in a pull request.
The code:
class Consumer(fn: PubSubMessage => Any) extends Runnable {
def start () {
val myThread = new Thread(this) ;
myThread.start() ;
}
def run {
whileTrue {
asList match {
case Some(Some(msgType) :: Some(channel) :: Some(data) :: Nil) =>
Logger.info("Engine: redis traffic")
msgType match {
case "subscribe" | "psubscribe" => fn(S(channel, data.toInt))
case "unsubscribe" if (data.toInt == 0) =>
fn(U(channel, data.toInt))
break
case "punsubscribe" if (data.toInt == 0) =>
fn(U(channel, data.toInt))
break
case "unsubscribe" | "punsubscribe" =>
fn(U(channel, data.toInt))
case "message" | "pmessage" =>
fn(M(channel, data))
case x => throw new RuntimeException("unhandled message: " + x)
}
case _ => Logger.error("Engine: weird redis message")
}
}
}
}
case x => throw new RuntimeException("unhandled message: " + x)
}
case Some(Some("pmessage")::Some(pattern)::Some(channel):: Some(message)::Nil)=>
fn(M(channel, message))
asList match is missing a case

scala actor message definition

Do i need to define class for message i want to retrieve on a scala actor?
i trying to get this up
where am i wrong
def act() {
loop {
react {
case Meet => foundMeet = true ; goHome
case Feromone(qty) if (foundMeet == true) => sender ! Feromone(qty+1); goHome
}}}
You can think it as a normal pattern matching just like the following.
match (expr)
{
case a =>
case b =>
}
So, yes, you should define it first, use object for Message without parameters and case class for those has parameters. (As Silvio Bierman pointed out, in fact, you could use anything that could be pattern-matched, so I modified this example a little)
The following is the sample code.
import scala.actors.Actor._
import scala.actors.Actor
object Meet
case class Feromone (qty: Int)
class Test extends Actor
{
def act ()
{
loop {
react {
case Meet => println ("I got message Meet....")
case Feromone (qty) => println ("I got message Feromone, qty is " + qty)
case s: String => println ("I got a string..." + s)
case i: Int => println ("I got an Int..." + i)
}
}
}
}
val actor = new Test
actor.start
actor ! Meet
actor ! Feromone (10)
actor ! Feromone (20)
actor ! Meet
actor ! 123
actor ! "I'm a string"
Strictly no, you can use any object as the message value. A message could be an Int, String or a Seq[Option[Double]] if you like.
For anything but play-around code I use custom immutable message classes (case-classes).