Request-Response with the ask pattern - scala

I am fairly new to Akka and went through this request-response example of the Akka documentation.
I understood this pattern works like the following:
Dave asks Hal by sending a message of Hal's protocol.
Hal answers by sending a message of its own protocol to Dave.
Dave, who does not know Hal's protocol gets the response adapted and re-sent to itself.
Dave receives the adapted response and continues with its payload.
context.ask(dave, Dave.Request) {
case Failure(exception) => throw exception
case Success(response) => AdaptedResponse(response.payload)
}
But what happens, if Dave needs response.payload diretly on the spot? Is this even possible?

In Akka Typed, it's not possible using context.ask, though I would question why you specifically need it.
As an alternative, when you have two actors which interact, you can define a joint-protocol between them:
object Hal {
sealed trait Command
sealed trait CommandFromDave extends Command {
def replyTo: ActorRef[Dave.ResponseFromHal]
}
case class OpenThePodBayDoorsPlease(override val replyTo: ActorRef[Dave.ResponseFromHal]) extends CommandFromDave
}
object Dave {
sealed trait Command
sealed trait ResponseFromHal extends Command
case class MessageFromHal(msg: String) extends ResponseFromHal
}
Then Dave can just
hal ! Hal.CommandFromDave(context.self)
and get the response directly from Hal (and you can schedule a message to yourself to account for the timeout).
Note that this really entangles two actors together. It's suitable for cases like where a parent actor defers a long-running task to a child actor, but it's a really questionable approach in most/all other scenarios.

Related

Scala akka how create entry point for event source?

I've been struggling to learn akka actors and I REALLY need your help guys!
So my goal is basically to write a simple auction agent. And AKKA actually has an example on how to do it https://doc.akka.io/docs/akka/current/typed/replicated-eventsourcing-auction.html! The problem is, I have no idea how to run it. Now I've spent like 3 days on trying to get it to work before asking for your help but I've completely lost it..:/
So, I started to learn about typed actors first and how they work. I've managed to actually print something on the screen by creating a simple actor system like this that I've found on the internet where I have a simple order actor (typed) and on its apply method I can print the incoming order:
//Entry point inside main(args <...>)
val orderProcessor: ActorSystem[OrderProcessor.Order] = ActorSystem(OrderProcessor(), "main")
//create a new order
orderProcessor ! Order(0, "Bananas")
//<..printing something inside the actor when receiving this message>
Now the auction example uses EventSourcedBehavior so I came to the conclusion that next step is to learn about event sourcing in Akka (hopefully this isn't confusing so far or hopefully I'm on the right path) So I went to the official documentation of Akka's event sourcing https://doc.akka.io/docs/akka/current/typed/persistence.html#module-info and I took their example:
object MyPersistentBehavior {
sealed trait Command
final case class Add(data: String) extends Command
case object Clear extends Command
sealed trait Event
final case class Added(data: String) extends Event
case object Cleared extends Event
final case class State(history: List[String] = Nil)
val eventHandler: (State, Event) => State = { (state, event) =>
event match {
case Added(data) => state.copy((data :: state.history).take(5))
case Cleared => State(Nil)
}
}
val commandHandler: (State, Command) => Effect[Event, State] = { (state, command) =>
command match {
case Add(data) => Effect.persist(Added(data))
case Clear => Effect.persist(Cleared)
}
}
def apply(id: String): Behavior[Command] =
EventSourcedBehavior[Command, Event, State](
persistenceId = PersistenceId.ofUniqueId(id),
emptyState = State(Nil),
commandHandler = commandHandler,
eventHandler = eventHandler)
}
Now that is great! Very simple and concise.
The problem is, I don't understand where the entry point is?
Like for orderProcessor (first example that I've shown) it is obviously just to create a new ActorSystem and thats it, but I can't find any information on this example. I've tried soooo many different projects from github and none of them very simple enough for me to understand. To be fair most of them had tests, but tests didn't really help me much.
Please, any help, any tips would be SOOO much appreciated, I'm really struggling guys!
Love Yall !<3
You have to obtain ActorRef[MessangeType] to be able to send MessageType to it.
Existing actor has context (passed as an argument with Behavior definition) where you can create a child like:
val actorRef = context.spawn(behavior)
but you can also create it top-level from ActorSystem (then the system is the parent directly)
val actorRef = system.systemActorOf(behavior)
So in your case it could be something like:
val actorRef = system.systemActorOf(MyPersistentBehavior("test"))
actorRef ! MyPersistentBehavior.Add("test")
alternatively you can context.spawn it inside Behavior[OrderProcessor.Order] defined for your ActorSystem, then you'll talk to actorRef through system which would send commands to persistent actor.
I understand your paint, unfortunately Akka Documentation give only Snippets as samples in documentation and they are most of the time not complete and hard to understand.
You can find in their Github complete examples I guess you can understands things better this way.
If you want to see a full fledged Proof of Concept application with Akka, I have a blog about it which you can find here.

Akka - how to know if a message is a tell or an ask?

Is there any way to determine if a message is a tell or an ask?
Use case:
I'm seeing cases where a library is used from outside of an actor and tells are used for the message. Because the library will reply with the result for success/failure, yet me don't care about it in the usage, we're using tell and receiving back a message to a context that isn't an actor. By default the message goes to deadLetters which is fine but it logs the message. You can adjust the logging to shut up the messages but I'm wondering if there is any way to determine if the message is a tell or an ask from inside the library without doing something like having a specific message type for fire and forget vs asks.
I always include a "reply-to" field in my message types. Sometimes I make it an Option[ActorRef] but often I use a repeated parameter (which generalizes the response transmission and makes all cases cleaner–no None / Some(replyTo) / List(replyOne, replyTwo …) etc.) The repeated parameter approach is facilitated by an implicit class that allows fanout by providing a !* method.
So, something like this:
case class Req(i: Int, s: String, replyTo: ActorRef*)
case class Resp(mesg: String)
class MyActor extends Actor {
...
def receive = {
case Req(i, s, replyTo) => ... replyTo !* Resp("Consider it handled")
...
}
...
}

Rewrite the Scala actors in Akka

Update: I've rewritten it in wonky-style and posted it on github - I would appreciate some feedback: https://github.com/drozzy/parallel-discrete-event-akka/tree/master/src/main/scala
Can anyone help me re-write "Parallel discrete event simulation" example from the "Chapter 32: Actors and Concurrency" from Programming in Scala, 2nd, by Martin Odersky?
It was written originally in Scala actors, but translating to Akka I encouter a lot of problems.
Some examples
Actor inheritance (p. 708)
Code like this:
trait Simulant extends Actor
class Wire extends Simulant
I have no idea how to translate to Akka, since in my understanding we never directly instantiate them.
Main Loop
The author constantly uses loops in actors, and I have no idea what they are about:
def act() {
loop {
if (running && busySimulants.isEmpty)
advance()
reactToOneMessage()
}
}
Types
Mostly though, I am struggling with strong types -- it seems Akka, due to requiring ActorRefs prevents me from depending on a specific type of an actor. For example, in the book, the following:
trait Simulant extends Actor {
val clock: Clock
...
depends on a strongly-typed actor Clock. And then it is simply "instantiated" in the implementing actor:
class Wire(name: String, init: Boolean) extends Simulant {
def this(name: String) { this(name, false) }
def this() { this("unnamed") }
val clock = Circuit.this.clock
In my implementation I have something along the lines of:
trait Simulant extends Actor {
val clock: ActorRef
...
and I have no idea how to "instantiate" it. What I have now (untested) is:
class Wire(val clock:ActorRef, name:String, init: Boolean) extends Actor{
def this(clock:ActorRef, name:String) {this(clock, name, false)}
def this(clock:ActorRef){this(clock, "unnamed")}
so I just end up draggin the actor refs around the constructors!
Hooking up components
How do I hook up components to each other? For example, hook-up an AndGate to a Wire - such that any time a signal on the wire changes it sends a message to the gate.
I do it by sending Add messages (i.e. AndGate sends Add to Wire so that wire can add it to the list of its subscribers), and so have to wait for all of them to arrive before starting the simulation. Is there any way to avoid that (the waiting)? (In original implementation the with Scala Actors, some actors were just accessed from global scope, and sometimes actors called other actor's methods directly!)
Source Code
The source code of the example can be found in full at the following url:
http://booksites.artima.com/programming_in_scala_2ed/examples/html/ch32.html
under the heading: 32.6 A longer example: Parallel discrete event simulation
P.S.: I'm new to akka, so forgive my ignorance.
I can not provide any migrated source code, but this link might help you:
actors migration guide.
Some comments:
Actor Inheritance
You can do this in Akka, but class Wire has to implement the receive method.
Main Loop
In Akka you implement the receive method instead of the main loop.
Types
You can use an ActorRef as constructor parameter, but it has to be created (and started) before calling the constructor, e.g. with context.system.actorOf(...).
And there is something called Typed Actors in Akka.
I also strongly encourage you to have a look at the documentation.
EDIT
I had a (quick) look at the source code, these are my findings:
In Scala it is not so common as in Java (and not enforced) that only one public class exists per file (although it can improve compile speed).
Demo.scala: Line 11, Use var instead of val
Constructor initialization (e.g. in FullAdder, Gate, ...): You should be careful about
that, because the constructor is executed every time the actor is restarted; maybe using
the preStart method would be better.
FullAdder, HalfAdder: An actor who doesn't react to messages (or only returning Unit) is a
strange thing in my opinion. Maybe you find another solution for constructing an adder.
Clock.advance: Using return is not good scala style (and I believe it doesn't work
in this case). Use else instead.

Akka and Actor behavior interface

I just start trying myself out with Scala. I grow confident enough to start refactoring an ongoing multi-threaded application that i have been working on for about a year and half.
However something that somehow bother and i can't somehow figure it out, is how to expose the interface/contract/protocole of an Actor? In the OO mode, i have my public interface with synchronized method if necessary, and i know what i can do with that object. Now that i'm going to use actor, it seems that all of that won't be available anymore.
More specifically, I a KbService in my app with a set of method to work with that Kb. I want to make it an actor on its own. For that i need to make all the method private or protected given that now they will be only called by my received method. Hence the to expose the set of available behavior.
Is there some best practice for that ?
To tackle this issue I generally expose the set of messages that an Actor can receive via a "protocol" object.
class TestActor extends Actor {
def receive = {
case Action1 => ???
case Action2 => ???
}
}
object TestActorProtocol {
case object Action1
case object Action2
}
So when you want to communicate with TestActor you must send it a message from its protocol object.
import example.TestActorProtocol._
testActorRef ! TestActorProtocol.Action1
It can become heavy sometimes, but at least there is some kind of contract exposed.
Hope it helps

How to represent that an Akka actor is in a long running operation using FSM-s

My actor that is described with an FSM is waiting for a trigger (in Idle state). When it gets it it starts processing some data (and goes to Running state) and when it is done it goes back to Idle state.
If I understand the FSM model correctly, from this point of view there were two events:
processing started (Idle->Running) and processing completed (Running->Idle).
But from the actor point of view there was only one message.
One possibility is to delegate the processing itself to another actor. So I can forward the triggering event and go to Running state, then when got the result I go to Idle.
It has the advantage that the FSM itself can quickly react to requests (e.g. asking what's the current state), but it makes the design more complicated.
Another one is to send a completed message to self when the actor has completed processing, which will trigger the Running -> Idle transition, but it looks a bit strange for me.
What other options do I have?
Note: there are several other states with various transitions so I'd like to stick to the FSM model.
Since it seems like you have an actor that needs to do processing and make transitions to an FSM, I suggest you follow these guidelines (some basic code outline follows this list):
Actor A receives the message in question that will trigger some processing
Actor A transitions a separate FSM actor, say F, (akka.actor.FSM) to the appropriate state. Actor A on startup would spawn the specific FSM to track the state for the corresponding context (e.g. for all transactions or state per transaction or some other context). The code outline below uses all processing or completed transactions as the context for the example but may need to be changed.
Actor A then triggers whatever processing should be triggered for the message. Remember actors shouldn't block generally, but here is an answer that provides more guidelines on when an Akka actor may block.
Alternative: If you can trigger long running processing without blocking and ensure you receive the necessary events after processing stages by the other party, then you could eliminate the front Actor A and just have the FSM actor F. You should look at onTransition in this case.
So my code outline suggestion is based on what I understood from the question is:
/* Events */
sealed trait MyEvents
case class ProcessingStarted(txnId: Long) extends MyEvents
case class ProcessingFinished(txnId: Long, result: Result) extends MyEvents
/* Valid states for your FSM */
sealed trait MyStates
case object Idle extends MyStates
/* Constructor arguments could be anything, I randomly chose a Long for a transaction ID which may be specific to a job */
case object Processing extends MyStates
/* define more case classes or objects depending on the rest of the states */
/* Valid internal state data types for FSM */
sealed trait MyDataTypes
case object Uninitialized extends MyDataTypes
case class StateData(processingIds: Seq[Long], resultMap: Map[Long, Result]) extends MyDataTypes
import akka.actor.{ Actor, ActorRef, FSM }
import scala.concurrent.duration._
class ActorF extends FSM[MyStates, MyDataTypes] {
startWith(Idle, Uninitialized)
when(Idle) {
case Event(ProcessingStarted(txnId), Uninitialized) =>
goto(Processing) using StateData(Seq(txnId), Map.empty[Long, Result])
case Event(ProcessingStarted(txnId), StateData(emptyIds, resultMap)) =>
goto(Processing) using StateData(Seq(txnId), resultMap)
}
when(Processing) {
case Event(ProcessingFinished(txnId, result), StateData(processingIds, resultMap)) => {
val remainingIds = processingIds diff Seq(txnId)
val newResultMap = resultMap + (txnId -> result)
if (remainingIds.isEmpty) {
goto(Idle) using StateData(remainingIds, newResultMap)
} else {
stay using StateData(remainingIds, newResultMap)
}
}
}
initialize()
}
// inside Actor A do something like this for creating the FSM actor (just like other actors)
val f = system.actorOf(Props(classOf[ActorF], this))
// send an event message to it just like other types of actors
f ! ProcessingStarted(txnId)
If you choose to trigger off non-blocking processing requests to other parts of your code you can use onTransition to add the trigger code in as necessary. You may also want to update the MyEvents case classes to a different tense. The event naming was used above was to show that something else was responsible for triggering that off (e.g. Actor A the received the initial message to do some things).
Also take note of Supervision capabilities of Akka which could be used here to supervise the actors in question.
For more details read the following which might help further with building your FSM, testing it, using non-blocking methods to trigger long-running processing externally. All of which might be useful for your needs:
Scala docs for Akka 2.2.x: FSMs
Scala docs for Akka 2.2.x: Testing
Scala docs for Akka 2.2.x: Akka IO for non-blocking
Scala docs for Akka 2.2.x: ZeroMQ