I'm currently tagging all my logs with trace details, whenever an actor or Future is encountered there is chance that a new thread would execute the next set of lines as a result I need update the span details.
Basically, I need to run few lines of code for every case in receive method.
class MyActor() extends Actor{
override def receive: Receive = {
case Foo() => {
//update span details
some logic for Foo
}
case Bar() => {
//update span details
some logic for BAR
}
case a: SomeType =>
//update span details
some logic for SomeType message
}
}
Is there any way to execute the update span details lines for every message by default something like #beforeEach
Since Receive is just PartialFunction[Any, Unit]:
def updateSpanDetails(pf: PartialFunction[Any, Unit]): PartialFunction[Any, Unit] = {
case msg if pf.isDefinedAt(msg) =>
// update span details
pf(msg)
}
class MyActor() extends Actor {
override def receive: Receive = updateSpanDetails {
case Foo() =>
???
case Bar() =>
???
case a: SomeType =>
???
}
}
Disclaimer: only mentally compiled
Related
From Akka Cookbook, example from chapter Persistent Actors. In SamplePersistentActor.scala there is line of code that I don't quite understand. Here's the full code of 2 files.
SamplePersistentActor.scala:
class SamplePersistenceActor extends PersistentActor {
override val persistenceId = "unique-id-1"
var state = ActiveUsers()
def updateState(event:Event) = state = state.update(event)
val receiveRecover: Receive = {
case evt: Event => updateState(evt)
case SnapshotOffer(_, snapshot: ActiveUsers) => state = snapshot
}
override val receiveCommand: Receive = {
case UserUpdate(userId, Add) =>
persist(AddUserEvent(userId))(updateState)
case UserUpdate(userId, Remove) =>
persist(RemoveUserEvent(userId))(updateState)
case "snap" => saveSnapshot(state)
case "print" => println(state)
}
}
SamplePersistentModel.scala:
sealed trait UserAction
case object Add extends UserAction
case object Remove extends UserAction
case class UserUpdate(userId: String, action: UserAction)
sealed trait Event
case class AddUserEvent(userId: String) extends Event
case class RemoveUserEvent(userId: String) extends Event
case class ActiveUsers(users: Set[String] = Set.empty[String])
{
def update(evt: Event)= evt match {
case AddUserEvent(userId) => copy(users + userId)
case RemoveUserEvent(userId) => copy(users.filterNot(_ == userId))
}
override def toString = s"$users"
}
My question
What is the purpose of = state (or = this.state if I'm correct) in line def updateState(event:Event) = state = state.update(event). Why can't we just use def updateState(event:Event) = state.update(event)?
Found similar in documentation example.
In your sample code:
def updateState(event: Event) = state = state.update(event)
is equivalent to:
def updateState(event: Event) = { state = state.update(event) }
So, updateState is a function of Event => Unit, which is exactly what method persist expects as its second parameter:
persist(AddUserEvent(userId))(updateState)
Below is the signature of method persist in Akka PersistentActor:
trait PersistentActor extends Eventsourced with PersistenceIdentity {
// ...
def persist[A](event: A)(handler: A => Unit): Unit = {
internalPersist(event)(handler)
}
// ...
}
It expects a EventType => Unit handler code block as its second parameter to handle specific persistence business logic that generally involves updating internal states of the actor.
Why can't we just use def updateState(event:Event) = state.update(event)?
The reason for the reassignment to the state variable is that update creates a new object. In other words, calling state.update doesn't mutate state; it makes a copy of state with the updated information.
This is the case with the example that you referenced:
var state = ExampleState()
def updateState(event: Evt): Unit =
state = state.updated(event)
Looking at the code for ExampleState, we see that the updated method actually creates a new ExampleState object:
def updated(evt: Evt): ExampleState = copy(evt.data :: events)
I have a actor like this:
class MyActor[T] extends Actor {
def receive = {
case Option1(t: T) =>
doWork(t) onComplete .....
case Option2 =>
}
def doWork(T): Future[T]{
}
}
Then I have an actor that inherits from the above:
class OtherActor extends MyActor {
val m = mutable.Map.empty[Int, User]
override def doWork(..) = {
//
}
}
Now in my OtherActor actor I want to add some methods to the receive method, how can I do this?
You can define the additional behavior in a Receive block inside OuterActor and chain that behavior to its parent's behavior with orElse:
class OtherActor extends MyActor {
val m = mutable.Map.empty[Int, User]
override def doWork(...) = ???
val otherBehavior: Receive = {
case ...
}
override def receive = otherBehavior.orElse(super.receive)
}
This is possible because Receive is just a type alias for PartialFunction[Any, Unit]. More information on composing actor behaviors is found here.
As a side note, you should prefer var m = immutable.Map.empty[Int, User] instead of val m = mutable.Map.empty[Int, User] in order to help avoid exposing the actor's state, as described in this answer.
Akka and Scala newbie here, please feel free to edit the question as necessary in order to clearly articulate my intent in the domain of Scala and Akka.
Before I show code snippets, here's the problem I want to solve: I essentially want to develop a common module for my team to use when they're developing their applications using Akka actors. I want to allow them to mixin a trait which will extend their receive functionality at runtime, mainly for logging purposes. I'm running into compile errors, which I'll explain soon.
But first, take for example, a simple main:
object Test extends App {
val system = ActorSystem("system")
val myActor = system.actorOf(Props(new MyActor), "myActor")
myActor ! "Hello world!"
}
Here's an example implementation of an actor that a team member might implement in his application:
class MyActor extends Actor with ActorLogger {
override def receive: Receive = {
case msg => {
log.info("testing ...")
}
case _ => throw new RuntimeException("Runtime Ex")
}
}
And here's an example of how I would provide a common trait for them to mixin:
trait ActorLogger extends Actor {
val log: DiagnosticLoggingAdapter = Logging(this)
abstract override def receive: Receive = {
case msg: Any => {
if (msg.isInstanceOf[String]) {
println("enter")
log.mdc(Map[String, Any]("someKey" -> 123))
super.receive(msg)
log.clearMDC()
println("exit")
}
}
case _ => throw new RuntimeException("Runtime Ex")
}
}
As you can see, I'm trying to add data to an MDC if the message so happens to be String (a basic example, in reality, I would check for some custom type of our own).
The error I get is:
Error:(29, 16) overriding method receive in trait ActorLogger of type =>
MyActor.this.Receive;
method receive needs `abstract override' modifiers
override def receive: Receive = {
^
What's wrong here? And is stackable traits the right to go away to achieve something like this? If not, what is the most idiomatic way?
More generally, is there another pattern being applied here besides "interceptor" pattern?
Thanks for all the help!
A solution without a hack with akka package:
import akka.actor.{Actor, ActorSystem, Props}
trait MyActorExtension extends Actor {
def receiveExtension: Receive = PartialFunction.empty
}
abstract class MyActor extends MyActorExtension {
protected def receiveMsg: Receive
def receive: Receive = receiveExtension orElse receiveMsg
}
trait ActorLogger1 extends MyActor with MyActorExtension {
abstract override def receiveExtension = {
case msg =>
println(s"********** Logging # 1: $msg")
super.receiveExtension.applyOrElse(msg, receiveMsg)
}
}
trait ActorLogger2 extends MyActor with MyActorExtension {
abstract override def receiveExtension = {
case msg =>
println(s"########## Logging # 2: $msg")
super.receiveExtension.applyOrElse(msg, receiveMsg)
}
}
class SpecificActor extends MyActor with ActorLogger1 with ActorLogger2 {
def receiveMsg = {
case someMsg =>
println(s"SpecificActor: $someMsg")
}
}
object Test extends App {
val system = ActorSystem("system")
val mySpecificActor = system.actorOf(Props(new SpecificActor), "SpecificActor")
mySpecificActor ! "Hello world!"
}
#### Logging # 2: Hello world!
****** Logging # 1: Hello world!
SpecificActor: Hello world!
aroundReceive is for Akka internal use and the stackable trair pattern is not that comfortable for this case.
I recommend you using Receive Pipeline for easy message interception.
I think that you need something like this
package akka
import akka.MsgsProt._
import akka.actor.{ Actor, ActorSystem, Props }
import scala.concurrent.duration._
sealed trait MsgProt
object MsgsProt {
case object FooMsg extends MsgProt
case object BarMsg extends MsgProt
}
trait Foo extends Actor {
override protected[akka] def aroundReceive(receive: Actor.Receive, msg: Any): Unit = msg match {
case FooMsg => println("Foo message")
case msg => super.aroundReceive(receive, msg)
}
}
trait Bar extends Actor {
override protected[akka] def aroundReceive(receive: Actor.Receive, msg: Any): Unit = msg match {
case BarMsg => println("Bar message")
case msg => super.aroundReceive(receive, msg)
}
}
class MyActor extends Actor with Foo with Bar {
override def receive: Actor.Receive = {
case _ => println("Nothing I know")
}
}
object Foo extends App {
val system = ActorSystem("foobar")
val myActor = system.actorOf(Props[MyActor])
implicit val timeout = 2 seconds
myActor ! FooMsg
myActor ! BarMsg
myActor ! "wrong message"
system.awaitTermination(10 seconds)
}
The output of this program is:
Foo message
Bar message
Nothing I know
Most important part is that package declaration - akka. Because method aroundReceive is limited only to akka package so you have to have some.package.akka and inside you can use that method aroundReceive. I think that it looks more like a hack not a solution but works. You can see more usage of this inside Akka itself ex. akka.DiagnosticActorLogging. But this is basically solution that you want to do with stacking Actors behaviour.
Say I have the below:
type Receive = PartialFunction[Any, Unit]
trait Functionality {
/**
* A set containing all Receive functions
*/
var allReceives: Set[Receive] = Set[Receive]()
}
Now other trait's can extend Functionality and do awesome stuff. Example:
trait LoadBalancer extends Functionality{
def body:Receive = {
case ...
}
allReceives += body
}
And ultimately my class:
class Main with LoadBalancer with SecurityFunctionality
with OtherFunctionality with Functionality{
def receive = {
case x if allReceives.foldLeft(false) { (z, f) => if (f isDefinedAt x) { f(x); true } else z } == true => ()
}
def body: Receive = {
}
allReceives += body
}
Question: What I wish to do is, in Main I need to call body function of all the traits that I have inherited. This way my code can be loosely coupled and I can add/remove functionality at a go.
The above works, but I do not like it as the compiler cannot guarantee that any trait that extends Functionality should add its body to allReceives.
I cannot declare def body:Receive in Functionality as then my implementation in Main will override body implementations of other traits. I am sure there should be a smarter way!
On second thought, composition really might be a better option here. This is a simpler solution, without any funny "abstract override"s:
object Main {
type Receive = PartialFunction[Any, Unit]
trait Receiver {
def receive: Receive
}
class LoadBalancer extends Receiver {
override def receive: Receive = {
case "one" => println("LoadBalancer received one")
}
}
class OtherFunctionality extends Receiver {
override def receive: Receive = {
case "two" => println("OtherFunctionality received two")
}
}
class MainFunctionality extends Receiver {
override def receive: Receive = {
case "three" => println("MainFunctionality received three")
}
}
class CompositeReceiver(receivers: List[Receiver]) extends Receiver {
override def receive: Receive = {
case msg =>
receivers.find(_.receive.isDefinedAt(msg)) map (_.receive(msg))
}
}
def main(args: Array[String]) {
val main = new CompositeReceiver(List(new OtherFunctionality, new LoadBalancer, new MainFunctionality))
main.receive("one")
main.receive("two")
main.receive("three")
}
}
This does not really answer your question, but here is a solution using the stackable traits pattern. Alas you still need to call super.receive as the last case in each trait, but I could not find a way around that yet.
object Main {
type Receive = PartialFunction[Any, Unit]
trait Receiver {
def receive: Receive
}
trait LoadBalancer extends Receiver {
abstract override def receive: Receive = {
case "one" => println("LoadBalancer received one")
case msg => super.receive(msg)
}
}
trait OtherFunctionality extends Receiver {
abstract override def receive: Receive = {
case "two" => println("OtherFunctionality received two")
case msg => super.receive(msg)
}
}
class Main extends Receiver {
override def receive: Receive = {
case "three" => println("Main received three")
}
}
def main(args: Array[String]) {
val main = new Main with OtherFunctionality with LoadBalancer
main.receive("one")
main.receive("two")
main.receive("three")
}
}
I'm trying to implement a Pub/Sub trait to mix into other akka actors using a stackable trait.
Here is what I came up with:
trait PubSubActor extends Actor {
abstract override def receive =
super.receive orElse {
case Subscribe(topic) => /* ... */
case Publish(topic, msg) => /* ... */
}
}
class MyActor extends Actor with PubSubActor {
override def receive = {
case SomeMessage(a, b, c) => /* ... */
}
}
At which point, the compiler throws back an error:
error: overriding method receive in trait MyActor... method receive needs `abstract override' modifiers.
Can you explain to me why this isn't working? How can I fix it so it works?
Thanks!
UPDATE
The following works:
trait PubSubActor extends Actor {
abstract override def receive =
super.receive orElse {
case Subscribe(topic) => /* ... */
case Publish(topic, msg) => /* ... */
}
}
class MyActor extends Actor {
override def receive = {
case SomeMessage(a, b, c) => /* ... */
}
}
class MyActorImpl extends MyActor with PubSubActor
But why? Why can I get the behavior I want this way but not the other? Any reasons? I can't seem to figure out the underlying difference between these two samples that makes the difference.
There's a simple and concise solution:
Define a Receiving trait that chains multiple receive functions using orElse :
trait Receiving {
var receivers: Receive = Actor.emptyBehavior
def receiver(next: Actor.Receive) { receivers = receivers orElse next }
def receive = receivers // Actor.receive definition
}
Using this in actors is easy:
trait PubSubActor extends Receiving {
receiver {
case Publish => /* I'm the first to handle messages */
}
}
class MyActor extends PubSubActor with Receiving {
receiver {
case SomeMessage => /* PubSubActor didn't handle, I receive the message */
}
}
First PubSubActor's receive will be called. If message wasn't handled it will be passed to MyActor's receive.
You can certainly achieve what you are looking for using Akka's composable actor feature. This is described a bit in Extending Actors using PartialFunction chaining.
First, the infrastructure code (straight from the docs):
class PartialFunctionBuilder[A, B] {
import scala.collection.immutable.Vector
// Abbreviate to make code fit
type PF = PartialFunction[A, B]
private var pfsOption: Option[Vector[PF]] = Some(Vector.empty)
private def mapPfs[C](f: Vector[PF] => (Option[Vector[PF]], C)): C = {
pfsOption.fold(throw new IllegalStateException("Already built"))(f) match {
case (newPfsOption, result) => {
pfsOption = newPfsOption
result
}
}
}
def +=(pf: PF): Unit =
mapPfs { case pfs => (Some(pfs :+ pf), ()) }
def result(): PF =
mapPfs { case pfs => (None, pfs.foldLeft[PF](Map.empty) { _ orElse _ }) }
}
trait ComposableActor extends Actor {
protected lazy val receiveBuilder = new PartialFunctionBuilder[Any, Unit]
final def receive = receiveBuilder.result()
}
Then the behaviors you want to be able to compose into actors:
trait PubSubActor { self:ComposableActor =>
receiveBuilder += {
case Subscribe(topic) => /* ... */
case Publish(topic, msg) => /* ... */
}
}
trait MyActor { self:ComposableActor =>
receiveBuilder += {
case SomeMessage(a, b, c) => /* ... */
}
}
And lastly, an actual actor that uses these composable behaviors:
class MyActorImpl extends ComposableActor with PubSubActor with MyActor
Try it the other way around:
object Subscription {
case object Subscribe
case object Unsubscribe
}
trait Subscription {
this: Actor =>
import Subscription._
var subscribers = Set.empty[ActorRef]
def receive: Receive = {
case Subscribe => subscribers += sender
case Unsubscribe => subscribers -= sender
}
}
class MyActor extends Actor with Subscription {
def receive = super.receive orElse {
case msg => // handle msg
}
}
Note that this still makes use of the stackable trait pattern, which is hidden by the fact that I've omitted the core. So something like this would still work (at least I think I will, ATM I have no time to check if it compiles).
class Core extends Actor {
def receive = Actor.emptyBehavior
}
class MyActor extends Core with Subscription
BTW, you can read more about the pattern (not related to Actors) here.
For the first, excuse me for my English
I think the point is that abstract override modifier requires presence of concrete implementation of receive method but in the first construction
class MyActor extends Actor with PubSubActor {
override def receive = {
case SomeMessage(a, b, c) => /* ... */
}}
it is not done
The reason is that scala compiler makes linearization for inheritance
so in receive's method chain we have the following sequence:
1) override def receive = {
case SomeMessage(a, b, c) => /* ... */
}
2) abstract override def receive = super.receive orElse {
case Subscribe(topic) => /* ... */
case Publish(topic, msg) => /* ... */
}
3) then Actor.receive - it hasn't an implementation
So PubSubActor.receive cannot be called because it use super.receive,
in its turn super.receive relies on Actor.receive, but Actor.receive hasn't an implementation.
In the second construction
class MyActor extends Actor {
override def receive = {
case SomeMessage(a, b, c) => /* ... */
}}
class MyActorImpl extends MyActor with PubSubActor
we have receive's method chain
1)
abstract override def receive = super.receive orElse {
case Subscribe(topic) => /* ... */
case Publish(topic, msg) => /* ... */
}
2)
override def receive = {
case SomeMessage(a, b, c) => /* ... */
}
3) then Actor.receive - it hasn't an implementation
So PubSubActor.receive can successfully call super.receive
Additional info:
Stackable traits
Scala language specification, see 5.1.2