Spray API blocked by bad Execution Context in Scala? - scala

I use the Spray API to listen for requests from a server. A computation in one specific scala class ends up blocking Spray from responding across the whole application. This is a slight simplification of the problem, but I can provide more info. if needed.
class SomeClass(implicit execc: ExecutionContext){
implicit val x = ...
val foo = Await.result(...someFunc(x))
}
I added this import and it resolved my issue:
import scala.concurrent.ExecutionContext.Implicits.global
Can anyone explain how or why this worked?
===================================================
Edit:
OuterClass instantiates SomeClass, but itself is never instantiated with the ExecutionContext parameter. It appears that it may be using the global execution context by default, and that is why it is blocking then?
class OuterClass(executor: ExecutionContext){
val s = new someClass
}
val x = (new OuterClass).someFunction

Spray route handler is a single actor that receives HTTP requests from Spray IO/Spray-can/library and passes them to the route handling function - essentially a partial function that has no concurrency on it's own. Thus if your route blocks, Spray will also block and requests will queue in the route handler actor queue.
There are 3 ways to properly handle blocking request processing in the route: spawn an actor per request, return Future of response or take request completion function and use it somewhere else unblocking the route (search for more detailed explanation if interested).
I can't be sure which execution context was used in your case, but it must have been very limited in terms of allocated threads and/or shared by your Spray route handler and long running task. This would lead to them both running on the same thread.
If you didn't have any execution context imported explicitly it must have been found through implicit resolution from regular scopes. You must have had one since you have it as a constructor parameter. Try to check your implicits in the scope to see which one it was. I'm curious myself whether it was one provided by Spray or something else.

Related

Scala Akka how to create a Typed ActorContext in route

I am pretty new in Scala Akka . Say I am spawning a Configuration child actor,
object Configuration {
def apply(): Behavior[ConfigurationMessage] = Behaviors.setup(context => new Configuration(context))
}
Now I need same context ActorContext[ConfigurationMessage] in my HTTP router to do some operation.
How can I create the same ActorContext there
The ActorContext cannot be used outside of the actor it's associated with, including in an HTTP router. Any ActorContext which leaks out of an actor (e.g. by sending it as a message) will, by design, throw an exception and not do anything for most operations if it's used outside of its actor.
The only operations on the ActorContext which could possibly be used outside of the associated actor are:
context.ask and friends can be just as easily replaced with a Future-returning ask on the target RecipientRef with the message send occurring in a foreach callback on the future.
context.executionContext: can just as easily use system.executionContext (which will typically be the same) or by looking up via dispatchers
context.pipeToSelf is probably best done as a send in a foreach callback on the future
context.scheduleOnce is better done using the system scheduler directly
context.self is kind of pointless, as you'd have to have the ActorRef already in order to leak the ActorContext
context.system is likewise pointless, as you already have the system

How to programmatically call Route in Akka Http

In Akka Http, it is possible to define the route system to manage a REST infrastructure in this way, as stated here: https://doc.akka.io/docs/akka-http/current/routing-dsl/overview.html
val route =
get {
pathSingleSlash {
complete(HttpEntity(ContentTypes.`text/html(UTF-8)`,"<html><body>Hello world!</body></html>"))
} ~
path("ping") {
complete("PONG!")
} ~
path("crash") {
sys.error("BOOM!")
}
}
Is there a way to programmatically invoke one of the route inside the same application, in a way that could be similar to the following statement?
val response = (new Invoker(route = route, method = "GET", url = "/ping", body = null)).Invoke()
where Response would be the same result of a remote HTTP call to the service?
The aforementioned API it's only to give an idea of what I have in mind, I would expect the capability to set the content type, headers, and so on.
In the end I managed to find out the answer to my own question by digging a bit more in Akka HTTP documentation.
As stated here: https://doc.akka.io/docs/akka-http/current/routing-dsl/routes.html, the Route is a type defined as follows:
type Route = RequestContext => Future[RouteResult]
where RequestContext is a wrapper for the HttpRequest. But is true as well that a Route can be converted, implicitly or not, to other function types, like this:
def asyncHandler(route: Route)(...): HttpRequest ⇒ Future[HttpResponse]
Hence, it is indeed possible to "call" a route by converting it to another function type, and then simply passing a HttpRequest build ad hoc, receiving a Future containing the desired response. The conversion required a little more time than the rest of the operations, but it's something that could be done while bootrstrapping the application.
Note: the conversion requires these imports, as stated here: https://doc.akka.io/docs/akka-http/current/introduction.html
implicit val system = ActorSystem("my-system")
implicit val materializer = ActorMaterializer()
implicit val executionContext = system.dispatcher
But these imports are already mandatory for the create of the service itself.
If this is for unit tests, you can use akka-http's test kit.
If this is for the application itself, you should not go through the route, you should just invoke the relevant services that the controller would use directly. If that is inconvenient (too much copy-pasta), refactor until it becomes possible.
As for the reason, I want my application to be wrapped inside both a web server (then use the route the “normal” way) and a daemon that responds to a message broker inbound message.
I have an application that does something like that actually.
But I came at this from the other way: I consider the broker message to be the "primary" format. It is "routed" inside of the consumer based purely on properties of the message itself (body contents, message key, topic name). The HTTP gateway is built on top of that: It has only a very limited number of API endpoints and routes (mostly for caller convenience, might as well have just a single one) and constructs a message that it then passes off to the message consumer (in my case, via the broker actually, so that the HTTP gateway does not even have to be on the same host as the consumer).
As a result, I don't have to "re-use" the HTTP route because that does not really do anything. All the shared processing logic happens at the lower level (inside the service, inside the consumer).

Is sending futures in Akka messages OK?

I'm working on implementing a small language to send tasks to execution and control execution flow. After the sending a task to my system, the user gets a future (on which it can call a blocking get() or flatMap() ). My question is: is it OK to send futures in Akka messages?
Example: actor A sends a message Response to actor B and Response contains a future among its fields. Then at some point A will fulfill the promise from which the future was created. After receiving the Response, B can call flatMap() or get() at any time.
I'm asking because Akka messages should be immutable and work even if actors are on different JVMs. I don't see how my example above can work if actors A and B are on different JVMs. Also, are there any problems with my example even if actors are on same JVM?
Something similar is done in the accepted answer in this stackoverflow question. Will this work if actors are on different JVMs?
Without remoting it's possible, but still not advisable. With remoting in play it won't work at all.
If your goal is to have an API that returns Futures, but uses actors as the plumbing underneath, one approach could be that the API creates its own actor internally that it asks, and then returns the future from that ask to the caller. The actor spawned by the API call is guaranteed to be local to the API instance and can communicate with the rest of the actor system via the regular tell/receive mechanism, so that there are no Futures sent as messages.
class MyTaskAPI(actorFactory: ActorRefFactory) {
def doSomething(...): Future[SomethingResult] = {
val taskActor = actorFactory.actorOf(Props[MyTaskActor])
taskActor ? DoSomething(...).mapTo[SomethingResult]
}
}
where MyTaskActor receives the DoSomething, captures the sender, sends out the request for task processince and likely becomes a receiving state for SomethingResult which finally responds to the captured sender and stops itself. This approach creates two actors per request, one explicitly, the MyTaskActor and one implicitly, the handler of the ask, but keeps all state inside of actors.
Alternately, you could use the ActorDSL to create just one actor inline of doSomething and use a captured Promise for completion instead of using ask:
class MyTaskAPI(system: System) {
def doSomething(...): Future[SomethingResult] = {
val p = Promise[SomethingResult]()
val tmpActor = actor(new Act {
become {
case msg:SomethingResult =>
p.success(msg)
self.stop()
}
}
system.actorSelection("user/TaskHandler").tell(DoSomething(...), tmpActor)
p.future
}
}
This approach is a bit off the top of my head and it does use a shared value between the API and the temp actor, which some might consider a smell, but should give an idea how to implement your workflow.
If you're asking if it's possible, then yes, it's possible. Remote actors are basically interprocess communication. If you set everything up on both machines to a state where both can properly handle the future, then it should be good. You don't give any working example so I can't really delve deeper into it.

What effect does using Action.async have, since Play uses Netty which is non-blocking

Since Netty is a non-blocking server, what effect does changing an action to using .async?
def index = Action { ... }
versus
def index = Action.async { ... }
I understand that with .async you will get a Future[SimpleResult]. But since Netty is non-blocking, will Play do something similar under the covers anyway?
What effect will this have on throughput/scalability? Is this a hard question to answer where it depends on other factors?
The reason I am asking is, I have my own custom Action and I wanted to reset the cookie timeout for every page request so I am doing this which is a async call:
object MyAction extends ActionBuilder[abc123] {
def invokeBlock[A](request: Request[A], block: (abc123[A]) => Future[SimpleResult]) = {
...
val result: Future[SimpleResult] = block(new abc123(..., result))
result.map(_.withCookies(...))
}
}
The take away from the above snippet is I am using a Future[SimpleResult], is this similar to calling Action.async but this is inside of my Action itself?
I want to understand what effect this will have on my application design. It seems like just for the ability to set my cookie on a per request basis I have changed from blocking to non-blocking. But I am confused since Netty is non-blocking, maybe I haven't really changed anything in reality as it was already async?
Or have I simply created another async call embedded in another one?
Hoping someone can clarify this with some details and how or what effect this will have in performance/throughput.
def index = Action { ... } is non-blocking you are right.
The purpose of Action.async is simply to make it easier to work with Futures in your actions.
For example:
def index = Action.async {
val allOptionsFuture: Future[List[UserOption]] = optionService.findAll()
allOptionFuture map {
options =>
Ok(views.html.main(options))
}
}
Here my service returns a Future, and to avoid dealing with extracting the result I just map it to a Future[SimpleResult] and Action.async takes care of the rest.
If my service was returning List[UserOption] directly I could just use Action.apply, but under the hood it would still be non-blocking.
If you look at Action source code, you can even see that apply eventually calls async:
https://github.com/playframework/playframework/blob/2.3.x/framework/src/play/src/main/scala/play/api/mvc/Action.scala#L432
I happened to come across this question, I like the answer from #vptheron, and I also want to share something I read from book "Reactive Web Applications", which, I think, is also great.
The Action.async builder expects to be given a function of type Request => Future[Result]. Actions declared in this fashion are not much different from plain Action { request => ... } calls, the only difference is that Play knows that Action.async actions are already asynchronous, so it doesn’t wrap their contents in a future block.
That’s right — Play will by default schedule any Action body to be executed asynchronously against its default web worker pool by wrapping the execution in a future. The only difference between Action and Action.async is that in the second case, we’re taking care of providing an asynchronous computation.
It also presented one sample:
def listFiles = Action { implicit request =>
val files = new java.io.File(".").listFiles
Ok(files.map(_.getName).mkString(", "))
}
which is problematic, given its use of the blocking java.io.File API.
Here the java.io.File API is performing a blocking I/O operation, which means that one of the few threads of Play's web worker pool will be hijacked while the OS figures out the list of files in the execution directory. This is the kind of situation you should avoid at all costs, because it means that the worker pool may run out of threads.
-
The reactive audit tool, available at https://github.com/octo-online/reactive-audit, aims to point out blocking calls in a project.
Hope it helps, too.

Scala how to use akka actors to handle a timing out operation efficiently

I am currently evaluating javascript scripts using Rhino in a restful service. I wish for there to be an evaluation time out.
I have created a mock example actor (using scala 2.10 akka actors).
case class Evaluate(expression: String)
class RhinoActor extends Actor {
override def preStart() = { println("Start context'"); super.preStart()}
def receive = {
case Evaluate(expression) ⇒ {
Thread.sleep(100)
sender ! "complete"
}
}
override def postStop() = { println("Stop context'"); super.postStop()}
}
Now I run use this actor as follows:
def run {
val t = System.currentTimeMillis()
val system = ActorSystem("MySystem")
val actor = system.actorOf(Props[RhinoActor])
implicit val timeout = Timeout(50 milliseconds)
val future = (actor ? Evaluate("10 + 50")).mapTo[String]
val result = Try(Await.result(future, Duration.Inf))
println(System.currentTimeMillis() - t)
println(result)
actor ! PoisonPill
system.shutdown()
}
Is it wise to use the ActorSystem in a closure like this which may have simultaneous requests on it?
Should I make the ActorSystem global, and will that be ok in this context?
Is there a more appropriate alternative approach?
EDIT: I think I need to use futures directly, but I will need the preStart and postStop. Currently investigating.
EDIT: Seems you don't get those hooks with futures.
I'll try and answer some of your questions for you.
First, an ActorSystem is a very heavy weight construct. You should not create one per request that needs an actor. You should create one globally and then use that single instance to spawn your actors (and you won't need system.shutdown() anymore in run). I believe this covers your first two questions.
Your approach of using an actor to execute javascript here seems sound to me. But instead of spinning up an actor per request, you might want to pool a bunch of the RhinoActors behind a Router, with each instance having it's own rhino engine that will be setup during preStart. Doing this will eliminate per request rhino initialization costs, speeding up your js evaluations. Just make sure you size your pool appropriately. Also, you won't need to be sending PoisonPill messages per request if you adopt this approach.
You also might want to look into the non-blocking callbacks onComplete, onSuccess and onFailure as opposed to using the blocking Await. These callbacks also respect timeouts and are preferable to blocking for higher throughput. As long as whatever is way way upstream waiting for this response can handle the asynchronicity (i.e. an async capable web request), then I suggest going this route.
The last thing to keep in mind is that even though code will return to the caller after the timeout if the actor has yet to respond, the actor still goes on processing that message (performing the evaluation). It does not stop and move onto the next message just because a caller timed out. Just wanted to make that clear in case it wasn't.
EDIT
In response to your comment about stopping a long execution there are some things related to Akka to consider first. You can call stop the actor, send a Kill or a PosionPill, but none of these will stop if from processing the message that it's currently processing. They just prevent it from receiving new messages. In your case, with Rhino, if infinite script execution is a possibility, then I suggest handling this within Rhino itself. I would dig into the answers on this post (Stopping the Rhino Engine in middle of execution) and setup your Rhino engine in the actor in such a way that it will stop itself if it has been executing for too long. That failure will kick out to the supervisor (if pooled) and cause that pooled instance to be restarted which will init a new Rhino in preStart. This might be the best approach for dealing with the possibility of long running scripts.