As a long time Java EE dev, I've used the MDC (Mapped Diagnostic Context) approach to deal with passing around contextual data relating to a request, e.g. a unique request token for tracking a request across many potential log events that occur during the lifetime of that request.
Given it's reliance on ThreadLocal, it's pretty clear that this approach implodes when using asynchronous techniques.
I'm still in the early days of learning Scala and, more relevant to this question, Akka. I have read plenty of forum postings confirming the incompatibility of Akka and MDC but have not yet uncovered a consistent strategy for mimicking the MDC approach in some way.
Is it simply best to just explicitly pass this sort of data around as part of the messages that get sent between actors? It kind of feels dirty but, at the same time, compatible with the ability to scale effortlessly.
Is there any other way to pass context to an Actor other than directly via messages? Also, has anyone faced this same challenge when using Play 2.0 Async blocks?
Companion object ActorSystem An actor system is a hierarchical group of actors which share common configuration, e.g. dispatchers, deployments, remote capabilities and addresses. It is also the entry point for creating or looking up actors. There are several possibilities for creating actors (see akka.
Akka's approach to handling concurrency is based on the Actor Model. In an actor-based system, everything is an actor, in much the same way that everything is an object in object-oriented design.
The actor context - the view of the actor cell from the actor. Exposes contextual information for the actor and the current message. There are several possibilities for creating actors (see akka. actor.
Akka is mostly based on ActorSystem and as a result dispatchers are said to be the main engine of an ActorSystem. Hence the saying- dispatchers are what makes Akka “tick”. In Akka, they are responsible for selecting an actor and it's messages and assigning them to the CPU.
I think you could use ThreadLocal
-s declared in a static context, same as executor implicit parameter in this code:
implicit val executor = context.dispatcher
val f = Future[Boolean] {
someTask()
} andThen {
case err if err.isLeft => log.error("Some error: " + err.left.get); false
case ok if ok.isRight => log.info("Good work: " + ok.right.get); true
}
Each time future submits task to a dispatcher, copy a thread safe context object from one thread into another. So, you need a custom dispatcher - by any means read ThreadLocal
, store it internally somewhere inside executor (dispatcher), then submit task that will firstly write into ThreadLocal
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With