Actoverse for Scala (Akka)
Actoverse API implementation for Akka Actor Framework
This library extends the Akka Actor system to realize captureing causal relationships and reverse debugging. Note that this implmentation is too experimental and there are several limitations for debugging.
Important: After ver 0.2.0, you don't have to rewrite source codes by introducing AspectJ.
project/plugins.sbt in your project with:
resolvers += Resolver.url("45deg/sbt-plugins", url("https://dl.bintray.com/45deg/sbt-plugins/"))(Resolver.ivyStylePatterns) addSbtPlugin("com.github.45deg" %% "actoverse-sbt" % "0.2.0")
Then, add the line below to
Add the settings to
(src/main/resources/)applications.conf in your project with:
# ActorPathes of the targets. You can use a regular expression. actoverse.target-actorpath = "akka://[SYSTEM NAME]/user/.+" # [Optional] The name of the ActorSystem for this debugger. actoverse.debugger-system-name = "ActoverseDebuggerSystem" # [Optional] The name of actors that is introduced into target ActorSystems. actoverse.debugger-actor-name = "__debugger" # Address and Port of WebSocket API Endpoint. actoverse.wshandler.hostname = "localhost" actoverse.wshandler.port = 3000
See also: An Example Repository.
How it works
DebuggingSystemcontrols actors. It commits a command from
WebSocketHandlerto actors and reports their states to the handler.
WebSocketHandlerperforms a mediator between the target system and the debugger UI.
- Incoming/outgoing messages are trapped by
DebuggingSupporters, which are accessories to actors.
The debugger attaches an additional information (internally, called
Envelope) to all the messages sent by actors with
!. It includes sender and receiver's Actor pathes, Lamport timestamps, and auto-generated UUIDs.
On the other hand, the
DebuggingSupporter of an receiving actor opens an envelope and delivers the original message to the actor. The idea of interception comes from Receive Pipeline Pattern
The figure below provides an overview of processing incoming messages (envelopes).
DebuggingSupporter stores the state (variables) of the actor itself every time when an actor finishes processing an incoming message, that is, finishes
receive. Currently, all
vars in the classes that extends
Actor are to be captured.
AspectJ (a framework for Aspect-oriented programming) enables the debugger to hook Actors' behaviors such as sending or receiving messages without modifying source codes. In this work, I used akka-viz and kamon-akka as reference and they were very helpful.
This implementation does not cover several functions of Akka or Scala, such as:
- To read/write external files or networks. The debugger cannot capture these modifications and restore a previous state of them.
- To deal with stopping and restarting actors. Because of Akka Actor's lifecycle, it is impossible to regenerate an actor with the same reference as the previous actor, which stopped manually. Therefore, restoring the system to the former condition is difficult.
- To variables which cannot be copied or duplicated. This framework copies and stores variables into a list. For the same reason, inconsistencies may occur when there is a reference variable of another object which can be modified from the outside of the Actor system.