My understanding of the persistenceId in a persistent actor in Akka is that it must have the same value upon reincarnations of the same actor in order to be able to recover state from the persistent store. How would this work in the event of a complete failure of the containing process? Does this mean that the persistenceId of an actor with a known path must be maintained in some other application specific persistent store?
I could understand how this would work with a specific actor with a known path, but how would this work with a worker actor that is controlled by a router pool?
Actors are created and stopped dynamically. How would I be able to associate a durable persistenceId with a specific actor in a router pool and be able to recover the state of the actor in the event of a failure in the containing process.
Related
do you have any experience with akka actor memory management/leak. Here I have a module use akka actor to communicate with other modules, but as time goes by one of module went down, because of heap memory size.
Is it necessary to send poison pill to children actor after it finished? Because every request in, I'd like to make another actor, each request. Is it necessary to send poison pill again in children actor, if they have their own children actor also?
ps: I'm using Scala Akka
Thanks
Yes, every Actor you create needs to be stopped explicitly. This is typically done by calling context.stop(self) from within the Actor (if it can determine that it is finished with its task) or having the supervisor stop it using context.stop(child).
To prevent running out of memory you can use bounded message queue aka mailbox on the receiving actor: http://doc.akka.io/docs/akka/snapshot/scala/mailboxes.html.
To pick how you want to manage child actors (restart, kill, etc) use supervisor strategy:
http://doc.akka.io/docs/akka/snapshot/general/supervision.html. Supervisor strategy can be picked at any level/parent.
I have a Scala application where I have several nodes. Each node has an ActorSystem with a main actor and each actor must have some ActorRef to certain actors (for example "Node 1" has "Actor3" and "Actor3" needs the ActorRef for "Actor7" and "Actor8" to do its work). My problem is that I don't know if another node ("Node2") has the "Actor1" or the "Actor7" I'm looking for.
My idea was to loop inside every MemberUp, using the ActorSelection several times and asking every new member if it has the actors I'm looking for. Is this the only way I can do it? Is there a way to do this more efficiently?
An alternative approach to ActorSelection can be lookup table. If you need to make lots of actor selection and actor creation is not so dynamic, it can be better solution.
On each node you can create a data structure like Map[String,List[String]] first key is Node name and List value is for actor refs in this node.
Trick is when any node has change for its actors (creating, stopping) another actor should notice other nodes about changes so any nodes have synchronised updated map.
If you guaranty it, then each node can lookup actor existence;
map.get(nodeName) match {
case Some(n) => n.contains(actorName)
case None => false
}
I've solved a very similar problem in our cluster by having a DiscoveryActor at a known path on every node. The protocol of the DiscoveryActor has
Register(name, actorRef)
Subscribe(name)
Up(name, actorRef)
Down(name, actorRef)
Each named actor sends a Register to its local DiscoveryActor which in turn broadcasts the Up to all local subscribers and all other DiscoveryActor's on other nodes, which in turn broadcast to their subscribers
The DiscoveryActor watches MemberUp/MemberDown to determine when to look for a new peer DiscoveryActor and broadcast its local registrations or broadcast Down for registrations of downed peers.
I am trying to build order fulfilment component with AKKA FSM. I have few basic doubts on how the state is been stored and taken further upon event from user.
Consider states
ORDER_CLEAN, ORDER_INIT, ORDER_PAYMENT_WAITING, ORDER_PAYMENT_SUCCESS, ORDER_DELIVERY, ORDER_COMPLETE
Events as
EV_CART_CHECKOUT, EV_PROCEED_PAYMENT, EV_PAYMENT_SUCCESSFUL, EV_ITEMS_PACKED, EV_DELIVERED
State changes as
(EV_CART_CHECKOUT, ORDER_CLEAN) -> ORDER_INIT
(EV_PROCEED_PAYMENT, ORDER_INIT) -> ORDER_PAYMENT_WAITING
(EV_PAYMENT_SUCCESSFUL, ORDER_PAYMENT_WAITING) -> ORDER_PAYMENT_SUCCESS
(EV_ITEMS_PACKED, ORDER_PAYMENT_SUCCESS) -> ORDER_DELIVERY
(EV_DELIVERED, ORDER_DELIVERY) -> ORDER_COMPLETE
Questions
When we create FSM actors starting at ORDER_CLEAN with event EV_CART_CHECKOUT, would this actor is alive till we bring it to ORDER_COMPLETE(assuming we stop actor at this state) state?
If yes to above point, in that case as we store order status on database how do we trigger new event on that actor? Is that do we need to maintain order_id to actor mapping and trigger event? What if there are 10K unique orders are currently being processed then we maintain mapping for all 10K actors is it? If so what is best data structure for maintaining these mappings for larger number of orders?
In continuation to 2nd point, what if actors go down how to bring back actors to same state? Is supervisor actor only way to solve this? Or do we need to check actor status and then send event?
At any point of state, user might not trigger next event may be for days, then is it good to keep actor live for such longer time or is it good to create new actor with updated state?
What are the better approaches to address these problems with akka FSM
If we are talking about non-persistent Actor, generally speaking, we
can't assume it will be alive between events. You simply might
restart or redeploy the service, so the answer to your 1. question
is no.
To trigger a new event to the actor, you should create this actor initialise state machine with last valid state from the DB.
You could either use Akka Persistence or just read current order state from the DB and pass it to the actor
Actors are very lightweight objects, but talking about 10k events I would suggest to terminate actor after each transition
I'm using the scala api for akka-persistence to persist a group of actor instances that are organized into a tree. Each node in the tree is a persistent actor and is named based on the path to that node from a 'root' node. The persistenceId is set to the name. For example the root node actor has persistenceId 'root'. The next node down has persistenceId 'root-europe'. Another actor might have persistenceId 'root-europe-italy'.
The state in each actor includes a list of the names of its children. E.g. the 'root' actor maintains a list of 'europe', 'asia' etc as part of its state.
I have implemented snapshotting for this system. When the root is triggered to snapshot, it does so and then tells each child to do the same.
The problem arises during snapshot recovery. When I re-create an actor with persistenceId = 'root' (by passing in the name as a constructor parameter), the SnapshotOffer event received by that actor is wrong. It is, for example, 'root-europe-italy....'. This seems like a contradiction of the contract for persistence, where the persistenceId identifies the actor state to be recovered. I got around this problem by reversing the persistenceId of node actors (e.g. 'italy-europe-root') so this seems to be something related to the way files are retrieved by the persistence module. Note that I tried other approaches first, for example I used a variety of separators between the node names, or no separator at all.
Has anyone else experienced this problem, or can an akka-persistence developer help me understand why this might have happened?
BTW: I am using the built-in file-based snapshot storage for now.
Thanks.
OK - so the issue was with Akka, and has now been resolved. See the related ticket to find out when the patch is released.
I want to convert some set of actors into FSM using Akka FSM. Currently system is designed in the way that every actor knows what to do with results of it's action and which actor is next in sequence of processing.
Now I want to have some sort of dedicated actors, which are doing only things they should know (and now know about entire message routing), and central FSM, which knows how to route messages and process transformation flow.
Client sends some request to FSM actor, FSM actor - on transition to next state - sends message to some actor in onTransition block. That actor replies to sender with some message, which is processed inside FSM state somehow until request is finished.
So far everything looks good, however I'm not sure what will happen if multiple clients will start interaction with FSM actor. Will the "workflow" be recorded somewhere, so flows from different clients won't collide at some point (like, FSM actor receives message from another client instead of originating one)?
Is it safe to have say 10 FSM actors and round-robin router, or I need to create new FSM actor on every request from client, and then kill it once finished?
Each Akka FSM actor will have only one state at a time, so you can't use multiple FSM actors with a round-robin router in this scenario. You may consider to create a new FSM actor on every request from a client. There are other options (a shared multi-user non-Akka FSM and a pool of FSM actors which may be "busy") but creation of a per-user FSM should be better solution because of the light-weight nature of Akka actors.