Scala: simple actor sending messages back to its sender - scala

I'm very new to Scala and have been fiddling around with an Actor. I've written one that I would have expected would keep sending messages back and forth forever. But when I run it, person1 sends a message that is successfully received by person2, but person1 never gets the message back. (I only get one "Sending" and one "Responding".) I'm sure I'm just misunderstanding something simple.
import scala.actors.Actor
import scala.actors.Actor._
case object Hello
class Person() extends Actor {
def talk(p:Person) {
Console.println("Sending")
p ! Hello
}
def act() {
loop {
react {
case Hello => {
Console.println("Responding")
// This doesn't actually send a message back to the sender.
sender ! Hello
}
}
}
}
}
object pingpong extends Application {
val person1 = new Person
val person2 = new Person
person1.start
person2.start
person1.talk(person2)
}
Any ideas?
EDIT: This works by explicitly passing the sender as part of the message, rather than using the sender method:
class Person() extends Actor {
def talk(p:Person) {
Console.println("Sending")
p ! (Hello, this)
}
def act() {
loop {
react {
case (Hello, theSender:Actor) => {
Console.println("Responding")
theSender ! (Hello, this)
}
}
}
}
}
Is the problem just that I shouldn't be using sender like I was using it, or is there something else going on? Can one use sender to send a message to the sender?

Related

Akka: First message going to dead letters, from second message it is all fine

I have supervisor actor which selects child actor based on command received, whenever it creates a new child actor and sends message(ask pattern) it timesout as child actor tries to send back response but it goes to dead letters.
Here is the child actor code
class IdActor(id: String, injector: Injector) extends Actor {
override def receive: Receive = {
case cmd: GenerateIdCmd =>
val parent = sender()
...
Future(idEvent) pipeTo sender //Issue is here going to dead letters
//Future(idEvent) pipeTo parent //This also leads to same problem
//parent ! idEvent // Same issue
}
}
Here is supervisor code
class IdSupervisor(injector: Injector) extends Actor {
override def receive: Receive = {
case cmd: GenerateIdCmd =>
...
val ref = context.child(cmd.id).getOrElse {
context.actorOf(Props(classOf[IdActor], cmd.id, injector), cmd.id)
}
ask(ref, cmd) pipeTo sender
}
}
Second message is flowing back to originator, first response from all new child actors going to dead letters from there afterwards going good.
Working Solution
Issue is with Supervisor, fixed code
class IdSupervisor(injector: Injector) extends Actor {
override def receive: Receive = {
case cmd: GenerateIdCmd =>
val originator = sender
...
val ref = context.child(cmd.id).getOrElse {
context.actorOf(Props(classOf[IdActor], cmd.id, injector), cmd.id)
}
ask(ref, cmd) pipeTo originator
}
}
I suspect that the issue doesn't actually occur when a child replies to the parent as you describe, but when the parent sends a message to a child and expects a reply:
val ref = context.child(cmd.id).getOrElse {
context.actorOf(Props(classOf[IdActor], cmd.id, injector), cmd.id)
}
ask(ref, cmd) pipeTo sender
An actor is started asynchronously upon creation. The observation that, when a new child is created, the first message to that child results in dead letters, while subsequent messages to that child result in the intended behavior, suggests an actor initialization issue. What's probably happening is that the child actors receive their first GenerateIdCmd message before they have completely started.
Never ever pipe directly to sender from future inside actor, sender is def and at the moment when future is completed, it might be already different one than you expect. One of solution is to store sender before future call:
class IdActor(id: String, injector: Injector) extends Actor {
override def receive: Receive = {
case cmd: GenerateIdCmd =>
...
val originalSender = sender
Future(idEvent) pipeTo originalSender
}
}

Akka-Http: How to return a response from an actor?

I am using an actor inside a request with the "ask" pattern:
val route =
pathPrefix("myapp") {
path("search") {
get {
(mainActorRef ? DoSomething("foo")).mapTo[ReturningType].map { result =>
complete(HttpEntity(ContentTypes.`application/json`, result ))
}
}
}
}
The problem is that the main actor communicates with other actors and gets an answer back from one of those actors like this:
class MainActor extends Actor {
override def receive: Receive = {
case d:DoSomething =>
anotherActor ! DoThis(d)
// received from anotherActor as reply to DoThis
case r:DoThisResponse =>
// how do I send the response back to my “route”?
pipe (Future{r}) to ???
}
}
How can I send this answer back to Akka-Http as response?
Using "sender()" in the main actor doesn't work as it won't be the right reference. Should I pass in the DoSomething some reference to use with "tell" (!) inside the main actor? How do I pass this reference?
Use forward instead of tell in the the MainActor when sending to anotherActor. That way anotherActor will not "see" MainActor as the sender .
So, basically, you send new messages in the intermediate steps with forward, but the actor in the line can simply respond to sender, since it does not see the intermediate actors.
Edit: a complete MainActor
class MainActor extends Actor {
override def receive: Receive = {
//delegating some more work to another container
case d:DoSomething =>
anotherActor forward DoThis(d)
// sending a response back to "route"
case r:DoThisResponse =>
sender ! Response
}
}

schedule and cancel an unknown number of message sendings

I want an Actor to be able to scheduleOnce() a message sending - any number of times - through message receipt (receive()). The cancellable thus created can be cancel()led through message receipt.
I encounter great difficulties to think about an architecture to handle this. Anyone'd have a clue on how to build this, with multiple Actors, functions, etc...?
Can I just cancel() the id defined as follows?
class myActor extends Actor {
def Receive = {
case msg(t) => {
createTrigger(t)
}
case _ => //do something
}
def createTrigger(t) => {
val id/*cancellable*/ = context.system.scheduler.schedule(t milliseconds,
someActor,
someMessage)
}
def cancelSchedule(cancellable) => {
cancellable.cancel()
}
}

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()

How to send a delayed response inside Scala actor

Non-actor class sends a synchronous message to actor like this:
val response = WorkData !? "hello"
If i want to respond to this message right away, than i will do this:
receive {
case "hello" => reply("world")
}
But if i need to reply some time in the future, than
how do i store the caller reference, and send the reply after that?
Reference to the current caller is stored at sender. E.g., it's perfectly valid to replace
receive {
case "hello" => reply("world")
}
with
receive {
case "hello" => sender ! "world"
}
You can store this ref hereafter in the mutable variable, or pass recursively through the actor's loop.
I generally store the sender reference to use it later.
receive {
case "hello" =>
val otherParty = sender
// more receives, etc
// ...
otherParty ! "world"
}
How about just spawning an anonymous actor that processes the message and respond when it's ready? This way the receiver just acts as a dispatcher. This does not need a mutable variable to store anything since you are using a closure here.
import scala.actors.Actor
import scala.actors.Actor._
case class Message(msg: String)
class MyReceiver extends Actor {
def act() {
react {
case Message(msg) =>
actor {
sender ! process(msg)
}
}
}
def process(msg: String): String =
"Result: " + msg
}
object Main {
def main(args: Array[String]) {
val a = new MyReceiver
a.start()
val res = a !? Message("foo")
println(res)
}
}
Regards, raichoo