How to implement factory of Akka actors? - scala

Let's say I have DAO Actors (CassDaoActor, VerticaDaoActor, etc) that respond to message 'Read'.
First of all, is there a way to express a interface or abstract class that defines the message 'Read' that extending actors should implement?
Now assume it's only at runtime that I could get to know which Actor needs to be created based on the configured db. For example, if configured db is cassandra, I need to create CassDaoActor, etc. This apparently is a typical use case for Factory Method Pattern as we know. I want to understand how can we implement such a thing? Evidently we can't pass "context" around since it looses content outside the scope of the actor.
Please suggest.
What I have tried so far is that I am returning respective props based on the configured db to the actor within which I need to create these actors.
object `package` {
val CASS = "cass"
val VERTICA = "vertica"
def getDAOProps(db: String): Props = db match {
case CASS => CassDaoActor.props
case VERTICA => VerticaDaoActor.props
}
}
// SupervisorActor
val db = configuredDb()
context.actorOf(getDAOProps(db), db)

Related

How to mock actors in a cluster sharding test environment?

I have managed to setup a test environment for event sourced behaviors with akka and scala and can correctly run unit testing on self-contained actors by doing
class CQRSActorSpec
extends ScalaTestWithActorTestKit(
EventSourcedBehaviorTestKit.config.withFallback(CQRSActorSpec.config)
)
then creating my testkit
private val myTestKit = EventSourcedBehaviorTestKit[Command, Event, State](system, MyActor)
and using it to issue commands
val result = myTestKit.runCommand[Response](StartJob(parameters, _))
result.reply shouldBe Done
result.event shouldBe Started(parameters)
result.state shouldBe ProcessingJob
Now I want to unit test an actor that in its lifecycle calls another actor, this is because I'm using the saga pattern, so the actor I'm testing is the supervisor of the saga and must call the involved parties.
So far I managed to do the following:
val mockParty = Behaviors.receiveMessage[Party.Command] { msg =>
val reply = msg match {
case _ => Done
}
msg.replyTo ! reply
Behaviors.same
}
ClusterSharding(system).init(Entity(Party.Key) { _ => mockParty })
this runs ok in the first test, but then when I have to test another, say a failure case, of course the second call will not work because there's already an entity registered in the cluster sharding and I cannot override that behavior. Also, there is no way to reset the cluster sharding.
Has anyone insights on how to solve this problem? Are there other utilities for testing cluster sharding that I'm not aware of? I found the documentation a bit lacking.
The root of the problem is using ClusterSharding(system) in your code which will create the real ClusterSharding object, which like you said you have no control of for tests. Instead, you should pass the ClusterSharding object from outside so that you can pass stub/mock implementation of it.
This is outline of what I am talking about rendered in Java:
Let's assume persistent actor/event sourced behavior of type EntityA will create and interact with another persistent actor/event sourced behavior of type EntityB.
Somewhere you in your application code you will have the ClusterSharding.init(..) call for the EntityA:
ClusterSharding sharding = ClusterSharding.get(actorSystem); //the real stuff in the app
sharding.init(
Entity.of(
EntityA.ENTITY_TYPE_KEY,
entityContext ->
EntityA.create(
entityContext.getEntityId(),
sharding
)
)
);
Note how the sharding object is passed to create method of EntityA and is the ClusterSharding object that EntityA interacts with.
In unit test this code will not be invoked, instead you can inject your own implementation of ClusterSharding when initializing the testKit:
//this is in test
ClusterSharding sharding = new ClusterShardingStub(); //your stub/mock
var esbtk =
EventSourcedBehaviorTestKit.create(
testKit.system(),
EntityA.create("entityId", sharding));
So now somewhere in the logic of your EntityA implementation you will presumably call sharding.entityRefFor(...) to get hold of instance of EntityRef<EntityBProtocol>. What you need to do is to program your stub/mock to return TestEntityRef.of(..) instance:
TestProbe<EntityBProtocol> testProbe = TestProbe.create(testKit.system());
EntityRef<EntityBProtocol> ref = TestEntityRef.of(EntityB.ENTITY_TYPE_KEY, "entityId", testProbe.ref());
And now any interactions that EntityA has with EntityB can be asserted using the TestProbe instance.

How do I specify type parameters via a configuration file?

I am building a market simulator using Scala/Akka/Play. I have an Akka actor with two children. The children need to have specific types which I would like to specify as parameters.
Suppose that I have the following class definition...
case class SecuritiesMarket[A <: AuctionMechanismLike, C <: ClearingMechanismLike](instrument: Security) extends Actor
with ActorLogging {
val auctionMechanism: ActorRef = context.actorOf(Props[A], "auction-mechanism")
val clearingMechanism: ActorRef = context.actorOf(Props[C], "clearing-mechanism")
def receive: Receive = {
case order: OrderLike => auctionMechanism forward order
case fill: FillLike => clearingMechanism forward fill
}
}
Instances of this class can be created as follows...
val stockMarket = SecuritiesMarket[DoubleAuctionMechanism, CCPClearingMechanism](Security("GOOG"))
val derivativesMarket = SecuritiesMarket[BatchAuctionMechanism, BilateralClearingMechanism](Security("SomeDerivative"))
There are many possible combinations of auction mechanism types and clearing mechanism types that I might use when creating SecuritiesMarket instance for a particular model/simulation.
Can I specify the type parameters that I wish to use in a given simulation in the application.conf file?
I see two questions here.
Can I get a Class instance from a String?
Yes.
val cls: Class[DoubleAuctionMechanism] = Class.forName("your.app.DoubleAuctionMechanism").asInstanceOf[Class[DoubleAuctionMechanism]]
You would still need the cast, as forName returns Class[_].
Can I instantiate a type with type parameters are not known compile time?
Well sort of, but not really.
object SecuritiesMarket {
def apply[A, C](clsAuc: Class[A], clsClr: Class[C])(security: Security): SecuritiesMarket[A, C] = {
SecuritiesMarket[A, C](security)
}
}
I think auction mechanisms and clearing mechanisms are dependencies for SecurityMarket. I'm guessing you instantiate them in its constructor somehow (how?). If that's the case why not just pass them in as a constructor parameter?
Edit:
I don't see how I could create the child actors inside SecurityMarket
Answering this in the comments; Props[T] can also be written as Props[T](classOfT), which can be simplified as Props(classOfT). Those three are the same. So the following code:
val auctionMechanism: ActorRef = context.actorOf(Props[A], "auction-mechanism")
Can be replaced with:
val classOfA = Class.forName("path.to.A")
val auctionMechanism: ActorRef = context.actorOf(Props(classOfA), "auction-mechanism")
First, application.conf is a runtime artifact and its contents are as far as I know not normally parsed at compile time. When the file is parsed at runtime, the parser creates an instance of the class Config which then controls the Akka setup.
The Typesafe Config library project readme is quite nice and the linked documentation has all of the details:
https://github.com/typesafehub/config/blob/master/README.md.
Second, since template parameters are not available at runtime because of type erasure, you can't normally use application.conf to control templating. You could create a custom build step to parse application.conf and modify your code before compilation, but this is maybe not what you want. (And if you do want a custom build step, perhaps a different .conf would be appropriate.)
Instead you might try simply eliminating the type parameters for the securities market class. Then create a single, simple implementation of the auction and clearing actors. Implement these actors by reading the names of the respective mechanisms from application.conf, instantiating the configured mechanism reflectively, and delegating to the instantiated mechanism. The mechanism classes could be independent of Akka, which is perhaps nice if that's where you keep most of your logic?

Play WebSocketActor createHandler with custom name

I am using (learning to) handle websockets in play application.
My controller is using WebSocket.acceptWithActor
def clientWS = WebSocket.acceptWithActor[JsValue, JsValue] { _ =>
upstream => ClientSesssionActor.props(upstream)
}
and all is well except some other "supervisor" actor needs to be able to use context.actorSelection(...) to communicate with all/some of those ClientSessionActors.
But all my ClientSessionActors are created with a path like this one :
[akka://application/system/websockets/ REQ_ID /handler]
Here is the line where WebsocketActorSupervisor creates them :
val webSocketActor = context.watch(context.actorOf(createHandler(self), "handler"))
That is where the "handler" part of the path comes from.
I would like to pass in a specific name for my ClientSessionActor instead of getting "handler".
Overloading the whole call stack with one more parameter seems inelegant: there is WebSocketActor.scala with Connect, WebSocketActorSupervisor(props and constructor), WebSocketsActor receive and then everything inside the WebSocket.scala.
I know I can pass the supervisor reference to the props, but what about the case when the "supervisor" has been restarted and needs to reconnect with his minions.
One more thing, I realize that I might be able to get all the "handler" actors, but there are more than 2 kinds of handlers. Yes I could have them ignore msgs directed at the other groups of handlers but this just feels so redundant sending out 3 times more msgs than I should have to.
Any suggestions ?
James ? :)
Thank you
How about each ClientSesssionActor sends a Register message to supervisor on preStart and store them in eg. val sessions = new HashMap[String, ActorRef].
And then unregister by sending Unregister in postStop
private class WebSocketsActor extends Actor {
import WebSocketsActor._
def receive = {
case c # Connect(requestId, enumerator, iteratee, createHandler) =>
implicit val mt = c.messageType
context.actorOf(WebSocketActorSupervisor.props(enumerator, iteratee, createHandler),
requestId.toString)
}
}
Here is code how play creates actors for handling websockets, it names with requestId.
I have also same question :) why not make it to name with custom names.

Configuring actor behavior using typesafe Config and HOCON

I am building a large agent-based / multi-agent model of a stock exchange using Akka/Play/Scala, etc and I am struggling a bit to understand how to configure my application. Below is a snippet of code that illustrates an example of the type of problem I face:
class Exchange extends Actor {
val orderRoutingLogic = new OrderRoutingLogic()
val router = {
val marketsForSecurities = securities.foreach { security =>
val marketForSecurity = context.actorOf(Props[DoubleAuctionMarket](
new DoubleAuctionMarket(security) with BasicMatchingEngine), security.name
)
orderRoutingLogic.addMarket(security, marketForSecurity)
}
Router(orderRoutingLogic)
}
In the snippet above I inject a BasicMatchingEngine into the DoubleAuctionMarket. However I have written a number of different matching engines and I would like to be able to configure the type of matching engine injected into DoubleAuctionMarket in the application configuration file.
Can this level of application configuration be done using typesafe Config and HOCON configuration files?
interesting case. If I understood you right, you want to configure Market actor mixing in some MatchingEngine type specified in config?
Some clarification: you can't simply mix in dynamic type. I mean if you move MatchingEngine type to config - it will be known only at runtime, when config is parsed. And at that time you'll not be able to instantiate new DoubleAuctionMarket(security) with ???SomeClassInstance???. But maybe you could replace inheritance with aggregation. Maybe an instance of MatchingEngine can be passed to Market as parameter?
Now, how to obtain an instance of MatchingEngine from config? In short - Typesafe Config has no parser for FQCN properties, but it's not hard to do it yourself using reflection. This technique is used in many places in Akka. Look here first. provider property set as fqcn string and can be changed to other provider (i.e. RemoteActorRefProvider) in other configurations. Now look at how it's processed to obtain Provider instance. First it's just being read as string here. Then ProviderClass is used to instantiate actual (runtime) provider here. DynamicAccess is a utility helping with reflexive calls. It's not publicly accessible via context.system, but just take a piece of it or instantiate yourself, I don't think it's a big issue.
With some modifications, your code may look:
class Exchange extends Actor {
val orderRoutingLogic = new OrderRoutingLogic()
val matchingEngineClass = context.system.settings.config.getString("stocks.matching-engine")
val matchingEngine = DynamicAccess.createInstance[MatchingEngine](matchingEngineClass)
val router = {
val marketsForSecurities = securities.foreach { security =>
val marketForSecurity = context.actorOf(DoubleAuctionMarket.props(security, matchingEngine))
orderRoutingLogic.addMarket(security, marketForSecurity)
}
Router(orderRoutingLogic)
}
I've moved props to companion object of DoubleAuctionMarket as stated in Recommended Preactices of akka docs. Usage of Props(new Actor()) is dangerous practice.

Unit Testing AKKA actors

I am doing a web application with Scala and Akka actors and I'm having some troubles with the tests.
In my case I need to taste an actor who talks with the Database. To do the unit testing I would like to use a Fake Database but I can't replace the new with my desired fake object.
Let's see some code:
Class MyActor extends Actor {
val database = new Database()
def receive = { ... }
}
And in the tests I would like to inject a FakeDatabase object instead Database. I've been looking in Internet but the best that I found is:
Add a parameter to the constructor.
Convert the val database to a var so in the test I could access the attribute by the underlying and replace it.
Both solutions solve the problem but are very dirty.
Isn't a better way to solve the problem?
Thanks!
The two primary options for this scenario are:
Dependency Injection Use a DI framework to inject a real or mock service as needed. In Akka: http://letitcrash.com/post/55958814293/akka-dependency-injection
Cake Pattern This is a Scala-specific way of achieving something akin to dependency injection without actually relying on injection. See: Akka and cake pattern
Echoing the advice here, I wouldn't call injecting the database in the constructor dirty. It might have plenty of benefits, including decoupling actor behaviour from the particular database instance.
However if you know there is only ONE database you will be always using in your production code, then think about defining a package level accessible constructor and a companion object returning a Props object without parameters by default.
Example below:
object MyActor {
def props() : Props = Props(new MyActor(new Database()))
}
class MyActor private[package](database : IDatabase) extends Actor {
def receive = { ... }
}
In this case you will still be able to inject the test database in your tests case (given the same package structure), but prevent users of your code from instantiating MyActor with unexpected database instance.