Using locks on Akka Actors - scala

I have a Actor that goes like this (assume that the receive method is overridden somewhere else):
class MyClass extends Actor {
def method1() = { ... }
def method2() = { ... }
def method3() = {
this.synchronized {
....
....
}
}
}
What happens if I have a final field defined in my Actor as:
private val lockType = new AnyRef
I then can use this lock to synchronize my method3? What would be the difference? My understanding is that using this reference to lock on a method would make that reference unavailable until the lock is released.
In the above case, I use a lock that can function independently of the this reference and lock only when some action on method3 is made, while the this reference is still available for the other threads?

There's no need for synchronization inside of an actor. The actor will only ever process a single message at a time.

Related

How to get a case class's 'copy' to use an overridden 'clone'?

I suppose the obvious solution is to call .clone.copy everywhere, but there are certain applications where calling .copy without .clone might be dangerous or hard to debug.
This seems to demonstrate that clone (or the overridden clone), is not used by copy:
class Process {
def replicate: Process = {
println("Hello from Process.replicate")
new Process()
}
}
final case class Processes(
process1: Process,
process2: Process
) {
override def clone: Processes = Processes(
process1.replicate, process2.replicate)
}
val origProcesses = Processes(new Process, new Process)
val clonedProcesses = origProcesses.copy(process1 = new Process)
You could provide your own copy method:
final case class Processes(
process1: Process,
process2: Process
) {
override def clone: Processes = Processes(
process1.replicate, process2.replicate)
def copy(process1: Process = this.process1.replicate, process2: Process = this.process2.replicate): Processes = Processes(
process1, process2)
}
In which case, you won't get the "free" copy method provided by Scala, but you can still avoid implementing your own equals, hashCode and companion object apply, unapply etc.

Why creating an actor within actor is dangerous

The akka documentation is clearly stated that it is dangerous to create an actor within an actor like this:
class ActorA extends Actor {
def receive = ???
}
final class ActorB extends Actor {
def receive = {
case _ =>
val act = context.actorOf(Props(new ActorA))
}}
I understand that the Actor's apply method is accepting this reference of the creating actor. yet I couldn't understand (nor couldn't find any example) why this is harmful and what issues it can cause?
Let's tweak your example a little bit
class ActorA(str:String) extends Actor {
def receive = ???
}
final class ActorB extends Actor {
def receive = {
case _ =>
val act = context.actorOf(Props(new ActorA("hidden")))
}}
Most of the common use case of using actors are to handle failover and supervision, shen an actor fails and needs to be restarted, the actor system needs to know how to do that. When you use Props(Props(new ActorA)), you've hidden the parameter value of "hidden" by handling it yourself.
Rather than doing that if instead, you declare how to create instances of the actor, the actor system will know exactly what it needs to do when recreating an actor -
i.e. create an instance of ActorA with a constructor argument of "hidden".
Even with your example of Actor without param
context.actorOf(Props(new ActorA))
this way of instantiating actors within another actor is not recommended because it encourages to close over the enclosing scope, resulting in non-serializable Props and possibly race conditions (breaking the actor encapsulation).
I believe we are confusing creation and declaration. The doc says that
Declaring one actor within another is very dangerous and breaks actor encapsulation. Never pass an actor’s this reference into Props!
So the problem is declaration, not creation!
Let's look at Java's:
public class MyActor extends AbstractActor {
#Override
public Receive createReceive() {
return ReceiveBuilder.create()
.match(String.class, handleString())
.matchAny(x -> unhandled(x))
.build();
}
private FI.UnitApply<String> handleString() {
return message -> sender().tell("OK", getSelf());
}
class MyOtherActor extends AbstractActor {
#Override
public Receive createReceive() {
return ReceiveBuilder.create()
.match(String.class, handleString())
.matchAny(x -> unhandled(x))
.build();
}
private FI.UnitApply<String> handleString() {
return message -> sender().tell("OK-Inner", getSelf());
}
}
}
Now, if MyOtherActor was a normal class, we'd be able to instantiate it only from an instance of MyActor:
MyActor actor = new MyActor();
MyActor.MyOtherActor otherActor = actor.new MyOtherActor();
Which means that the constructor for MyOtherActor depends on the instance of MyActor!
Now, if Props are supposed to contain the "factory" of the actor. They need a factory method. If our MyOtherActor is declared as we did here, then our props would look like this (ish):
MyActor actor = ??? // how did you even get a reference to the actor and not the actorRef in the first place!
Props otherActorProps = Props.create(MyActor.MyOtherActor.class, () -> actor.new MyOtherActor());
And bang, here comes the kicker! Now your otherActorProps contains a reference to actor, i.e. you have closed over mutable state! If for whatever reason actor "dies", your props will still be referencing it, causing all sort of weirdness.
There is also the issue of how you get a reference to the actor in the first place, and not it's actorRef
IMHO, that's what the documentation is referring to, and not the fact of "creating" (i.e. instantiating, spawning) an actor within another one: that's absolutely normal and it's a routine operation of akka (that's why you can do getContext().actorOf(..) as well as actorSystem.actorOf(...)
The warning is there in the documentation because it's easy to accidentally close over the creating actor's state, including its this pointer (which you should never use in actor-based code).
In my experience, I've usually seen a props method put into an actor's companion object:
object ActorA {
def props() = Props(new ActorA)
}
Doing it that way ensures the returned Props isn't closing over an actor's state.
class ActorB extends Actor {
def receive = {
case _ =>
val actorB = context.actorOf(ActorA.props)
...
}
}
It's not as big of a possibility for actors that don't take constructor parameters, but once parameters come into play you need to be careful about closing over internal state.

How to construct an actor together with its wrapper?

I'm trying to write an actor called ActorManager which wraps another actor called RealActor. The idea is that the ActorManager can process all messages going in and out of RealActor, allowing to add additional logic like filtering or buffering. The outside world is supposed to communicate with the RealActor only through its manager, much like in real world.
A first draft would look like this:
class ActorManager(realActor: ActorRef) extends Actor {
def receive = {
case _ => { /* pre-process messages */ }
}
}
class RealActor(actorManager: ActorRef) extends Actor {
def receive = {
case _ => { /* actual business logic */ }
}
}
This however raises the question how to construct both actors at once, or more specifically how to define the corresponding Props given the circular dependency of the two actors. I'm not sure if the general lazy val pattern is applicable when defining Props.
I also would like to avoid the work-around of constructing one of the two first, combined with introducing an explicit Register protocol to connect them.
Such a case is much better solved by using an actor hierarchy instead of plain actor siblings. Since the main intent here is to hide the RealActor from the outside world, it makes much more sense that its ActorRef is accordingly wrapped/owned by the outer ActorManager.
This means that the RealActor reference has to be created within the ActorManager scope. This can be achieved by passing the parent an ActorRef => Props function, allowing to create the child actor:
// Parent
class ActorManager(getRealActorProps: ActorRef => Props) extends Actor {
val realActor = context.actorOf(getRealActorProps(self))
def receive = {
case _ => { /* pre-process messages */ }
}
}
// Child
class RealActor(actorManager: ActorRef) extends Actor {
def receive = {
case _ => { /* actual business logic */ }
}
}
object RealActor {
def propsActorManager(getRealActorProps: ActorRef => Props) =
Props(new ActorManager(getRealActorProps))
def propsRealActor(actorManager: ActorRef) =
Props(new RealActor(actorManager))
def props() =
Props(new ActorManager(actorManager => propsRealActor(actorManager)))
}
Note that it is now even possible to hide the fact that the RealActor is wrapped by providing an appropriate props definition, which builds the ActorManager -> RealActor hierarchy implicitly.
See also this blog post why flat actor hierarchies are considered an anti-pattern.
Something of this sort may work well for you:
import akka.actor._
class Manager extends Actor {
def realActor: ActorRef = context.child("real")
.getOrElse(context.actorOf(RealActor.props, "real"))
override def receive: Receive = {
case msg ⇒ realActor forward msg
}
}
object RealActor {
def props: Props = Props(new RealActor)
}
class RealActor extends Actor {
override def receive: Receive = {
case _ ⇒
}
}
Creating child actor through parent's context seems to be sufficient for creating parent-child hierarchy. The parent can be obtained by calling context.parent in child actor.

Akka cluster singleton as scheduler

I am running Play with an Akka cluster.
I need an "Singleton Scheduler" to execute some tasks every hour.
What I found out so far is, that I should use ClusterSinglegonManager.
But I am not sure how my Actor must look like.
In my opinion, I wouldn't need a "receive" Method.
That is, how I instatiate my Singleton:
system.actorOf(
ClusterSingletonManager.props(
singletonProps = MySingletonActor.props(configuration),
terminationMessage = PoisonPill,
settings = ClusterSingletonManagerSettings(system)),
name = "mysingletonactor")
That would fit:
object MySingletonActor {
def props(configuration: Configuration): Props = Props(new MySingletonActor(configuration))
}
class MySingletonActor(configuration: Configuration) extends Actor with ActorLogging {
context.system.scheduler.schedule(2 seconds, 2 seconds)(println("Hallo Welt"))
def receive = ???
}
But of course it raises exceptions, because of the missing implementation of the receive method. But it works.
What is the best way to go here?
It feels awkward to just schedule a "Tick" and handle the Tick in the receive Method...
class MySingletonActor(configuration: Configuration) extends Actor with ActorLogging {
case object Tick
context.system.scheduler.schedule(2 seconds, 2 seconds, self, Tick)
def receive = { case Tick => println("Hallo Welt") }
}
Is there any kind of a Singleton Scheduler in Akka?
Instead of writing ??? as receive method, you can use Actor.emptyBehavior to not raise an Exception. This is a Receive-expression that matches no messages at all, ever.

How to get a reference to an existing ActorSystem in Akka?

is it possible in Akka (scala) to get a reference to an existing ActorSystem?
I am working on a Spray application with another Actor for DB. I am also extending Directives to have an object per path. the directives are not actors by themselves, but they need to pass messages to the DBActor. here:
class HttpActor extends Actor with HttpService {
val actorRefFactory = context
def receive = runRoute(
IndexService.route ~
HostsService.route
)
}
object HostsService extends Directives{
def route(implicit dm: DetachMagnet2) = {
path("hosts") {
get {
detach() {
**dbActor ! CreateHost**
complete("get me hosts!")
}
} ~
post {
detach() {
entity(as[String]) { payload =>
complete(s"post hosts $payload")
}
}
}
}
}
}
is there a way for HostsService to discover the ActorSystem itself so he can find the DBActor, or must HttpActor pass it in? the latter seems less elegant, as it HostsService will need to become a class (not an object), so no longer a singleton.
From here:
there was a ticket for creating such a registry, but we were not
satisfied with what we got when trying to specify the semantics in
detail. One part is that we removed all global state so that different
parts of an application can use Akka without having to worry about
each other and a global feature would break this. Another is that it
would encourage get-or-create usage—my pet peeve—which would make the
semantics unclear: you give a name and a config, but if the name
already exists you potentially get back a differently configured
system (which is usually quite fatal).
There is nothing stopping you from putting a hashmap in some central
place of your application, (pre-)populate that with the actor systems
you need and be done, that's basically a one-liner (which is another
reason for not including it in Akka, because instead of a simple
solution to a very narrow problem we'd have to think of a solution to
a much more generic problem)
In your case, it's better to pass your system implicitly to the route function:
class HttpActor extends Actor with HttpService {
implicit val actorRefFactory = context
def receive = runRoute(
IndexService.route ~
HostsService.route
)
}
object HostsService extends Directives {
def route(implicit dm: DetachMagnet2, as: ActorContext) = {...}
}