ExecutionContext to use with mapAsync in Akka-Streams - scala

I am just getting started with Akka Stream and I am trying to figure something out:
Currently, in my flows I am using mapAsync() to integrate with my rest services, as recommended here.
I have been wondering, what execution context should the mapAsync() be using?
Should it be the dispatcher of my ActorSystem? The global?
Are there any non-obvious consequences in either case?
I realize it's probably a silly question, but I've never dealt with Akka previously, and in any scala apps involving Futures, I've only ever used the global execution context.

The mapAsync stage doesn't need an execution context, it only requires you to map the current stream element to a Future. The future's execution context depends on who creates it, the flow doesn't know anything about it.
More generally, a Future[A] is an abstraction that doesn't require you to know where it's running. It could even be a precomputed value that doesn't need an execution context:
def mappingFunction(x: Int) = Future.successful(x * 2)
Source(List(1, 2, 3)).mapAsync(1)(mappingFunction)
You only need to worry about ExecutionContexts when you create the Future, but in the case of mapAsync you're just returning one from a function. How to create the future is the function's responsibility. As far as the mapAsync stage is concerned, it just gets the future as the return value of the function, i.e. it doesn't create it.
Flows have a Materializer. Its current implementation is the ActorMaterializer, which materializes streams using an ActorSystem (and its dispatchers). You are not required to know the details of stream materialization though, streams work on a more abstract level and hypothetically you could have a different Materializer that doesn't work with an ActorSystem

Related

Control execution of IgniteFuture

I would like to execute an async method in Ignite cache and set a timeout for the execution. Moreover, I would like to specify the executor.
Using cache.getAsync is very close to the desired functionality but it does not accept a timeout and executor arguments.
Currently, a sub-optimal solution can be found in the following Scala snippet:
val igniteFuture = cache.getAsync(key)
igniteFuture.listenAsync(
(f: IgniteFuture[T]) => f.get(timeout.toMillis, TimeUnit.MILLISECONDS)), executor)
How can the desired functionality can be achieved with current Ignite building blocks?
I think, you are mixing concepts of futures and asynchronous operations. Futures are the objects, that can be either completed, or waited on. So, when you ask Ignite to perform an asynchronous operation, it gives you a future, that will be completed later at some point. You can specify a period of time in a IgniteFuture.get() method, or subscribe to completion of this future, by using IgniteFuture.listen() method.
But the way, that operations are performed, is incapsulated from you. You can configure sizes of internal thread pools though: https://apacheignite.readme.io/docs/thread-pools

Play's execution contexts vs scala global

How does the execution context from
import scala.concurrent.ExecutionContext.Implicits.global
differ from Play's execution contexts:
import play.core.Execution.Implicits.{internalContext, defaultContext}
They are very different.
In Play 2.3.x and prior, play.core.Execution.Implicits.internalContext is a ForkJoinPool with fixed constraints on size, used internally by Play. You should never use it for your application code. From the docs:
Play Internal Thread Pool - This is used internally by Play. No application code should ever be executed by a thread in this thread pool, and no blocking should ever be done in this thread pool. Its size can be configured by setting internal-threadpool-size in application.conf, and it defaults to the number of available processors.
Instead, you would use play.api.libs.concurrent.Execution.Implicits.defaultContext, which uses an ActorSystem.
In 2.4.x, they both use the same ActorSystem. This means that Akka will distribute work among its own pool of threads, but in a way that is invisible to you (other than configuration). Several Akka actors can share the same thread.
scala.concurrent.ExecutionContext.Implicits.global is an ExecutionContext defined in the Scala standard library. It is a special ForkJoinPool that using the blocking method to handle potentially blocking code in order to spawn new threads in the pool. You really shouldn't use this in a Play application, as Play will have no control over it. It also has the potential to spawn a lot of threads and use a ton of memory, if you're not careful.
I've written more about scala.concurrent.ExecutionContext.Implicits.global in this answer.
They are the same and point out to the default dispatcher of the underlying actor system in your
Play or Akka or combined application.
##Default Play's Context
play.api.libs.concurrent.Execution.Implicits.defaultContext
##Play's Internal Context
play.core.Execution.Implicits.internalContext
##Guice's EC Injected
class ClassA #Inject()(config: Configuration)
(implicit ec: ExecutionContext) {
...
}
But this is different:
scala.concurrent.ExecutionContext.Implicits.global
Also DB drivers, e.g. if you use slick, may come up with their own Execution Context. Anyway,
Best Practices:
Don’t use scala.concurrent.ExecutionContext.Implicits.global when you are using play or akka framework, in this way you may use more threads than optimum during high load so the performance may decrease.
Don’t be afraid! use the default dispatcher as much as you want everywhere unless you do some blocking task for example listening on network connection, or reading from db explicitly that makes you “current threed” waiting for the result.
Start with default executor and if you found Play / Akka not responding well during high load, switch to a new thread pool for time consuming computation tasks.
Computational tasks that are taking long time is not usually considered blocking. For example traversing an auto completion tree in the memory. But you may considered them blocking when you want to have your control structures remaining functioning once you have a time taking computational task.
The bad thing that may happen when you consider computational tasks as non-blocking is that the play and Akka message dispatcher will be paused when all threads are computing in heavy load. The pros of a separate dispatcher is that the queue processor doesn’t starve. The Cons with separate dispatcher is that you may allocate more threads that optimum and your overall performance will be decreased.
The difference is for high load servers, don’t worry for small projects, use the default
Use scala.concurrent.ExecutionContext.Implicits.global when you have no other executor running in your app. Don’t worry this is safe then.
Once you create Futures, use the default pool, this is the safest way unless you are sure that the future is blocking. Then use a separate pool or use blocking{} structure if possible.
Create a separate thread pool once
You Await for a future
You call Thread.sleep
You are reading a stream/socket/http call
Manually querying db with a blocking driver, (usually slick is safe)
Schedule a task to be run in 10 second
Schedule a task to be run every second
For map/recover operations of a future, use the default executor, usually this is safe
Exception handling is safe with default dispatcher
Always use Akka dispatchers with you in Play or Akka, has a nice way to define a new dispatcher in application.conf
PRELUDE: This question is from 6 years ago, since then many things have changed. I know this is not an answer to the original question, but I was fooled more than 1 day with the same confusion that the original question states; so I decided to share my research results with the community.
The latest update reagrding ExecutionContext, which perfectly applies to Play 2.8.15 is as follows. The Play 2.6 migration guide states:
The play.api.libs.concurrent.Execution class has been deprecated, as it was using global mutable state under the hood to pull the “current” application’s ExecutionContext.
If you want to specify the implicit behavior that you had previously, then you should pass in the execution context implicitly in the constructor.
So you cannot use play.api.libs.concurrent.Execution.Implicits.defaultContext anymore. The no-configuration, out-of-the-box practice is to provide an implicit value of type scala.concurrent.ExecutionContext for the controller, something like:
import scala.concurrent.ExecutionContext
#Singleton
class AsyncController #Inject()(cc: ControllerComponents, actorSystem: ActorSystem)(implicit exec: ExecutionContext) extends AbstractController(cc)
This means that none of the above answers hold, also the question itself is not relevant anymore, since play.core.Execution.Implicits.defaultContext is not available anymore.

Event based design - Futures, Promises vs Akka Persistence

I have multiple use cases which require predefined events to be fired based on a certain user actions.
e.g. let's say when NewUser is created in the application, it'll have to call CreateUserInWorkflowSystem and FireEmailToTheUser asynchronously. There are many other business cases of this nature where events will be predefined based on a usecase. I can use Promises/Futures to model these events as below
if 'NewUser' then
call `CreateUserInWorkflowSystem` (which will be Future based API)
call `FireEmailToTheUser` (which will be Future based API)
if 'FileImport' then
call `API3` (which will be Future based call)
call `API4` (which will be Future based call)
All those Future calls will have to log failures somewhere so failed calls can be retried etc. Note NewUser call won't be waiting for those Futures (events per say) to complete.
That was using plain Futures/Promises APIs. However I am thinking Akka Persistence will be an appropriate fit here and blocking calls can still run into Futures. With Akka persistence, handling failure will be easy as it provides it out of box etc. I understand Akka persistence is still in experimental stage but that doesn't seem to be a big concern as typesafe generally keeps these new frameworks into experimental state before promoting into future release etc. (same was true with Macros). Given these requirements do you think Futures/Promises or Akka persistence is a better fit here?
This is an opinion based question - not the best type to ask on SO. Anyway, trying to answer.
It really depends what you are more comfortable with and what your requirements are. Do you need to scale the system later beyond a single JVM - use Akka. Do you want to keep it more simple - use Futures.
If you use Futures you can store all state and actions to execute in a job queue/db. It's quite reasonable.
If you use Akka Persistence then obviously it will help you with persistence. Akka will help to perform supervison, recovery and retries easier. If your CreateUserInWorkflowSystem action fails result is propagated to supervising actor which probably restarts the failed actor and makes it retry for N times. If your supervising actor fails then his supervisor will do the right thing, or eventually the whole app will crash which is good. With Futures you would have to implement this mechanism yourself and make sure that application can crash when needed.
If you have completely independent actions then Futures and Actors sound about the same. If you have to chain actions and compose them, then using Futures will be a somewhat more natural thing to do: for comprehensions, etc. In Akka you would have to wait for a message and based on a type of a message perform next action.
Try to mock a simple implementation using both and compare what you like/dislike given your particular application requirements. Overall, both choices are good, but I'm slightly leaning towards actors in this case.

Using Futures in Akka Actors

I'm just starting to learn Akka Actors in Scala. My understanding is that messages received by an Actor are queued in an Actor's mailbox, and processed one at a time. By processing messages one at a time, concurrency issues (race conditions, deadlocks) are mitigated.
But what happens if the Actor creates a future to do the work associated with a message? Since the future is async, the Actor could begin processing the next several messages while the future associated with the prior message is still running. Wouldn't this potentially create race conditions? How can one safely use futures within an Actor's receive() method to do long running tasks?
The safest way to use futures within an actor is to only ever use pipeTo on the future and send its result as a message to an actor (possibly the same actor).
import akka.pattern.pipe
object MyActor {
def doItAsynchronously(implicit ec: ExecutionContext): Future[DoItResult] = {
/* ... */
}
}
class MyActor extends Actor {
import MyActor._
import context.dispatcher
def receive = {
case DoIt =>
doItAsynchronously.pipeTo(self)
case DoItResult =>
// Got a result from doing it
}
}
This ensures that you won't mutate any state within the actor.
Remember two things
The notion behind the term Future(a special actor) is that we can create an actor for any result while it(the result) is still being computed, started or finished but we can't have an address for that special actor or future.
Suppose I want to buy something (my result is buying something, and the process it to initiate steps to start buying procedure) we can create an actor for the result (buy) but if there is any problem and we can't buy the thing we will have an exception instead of the result.
Now how the above two things fit is explained below-
Say we need to compute the factorial of 1 billion we may think that it will take a lot of time to compute but we get the Future immediately it will not take time to produce the Future (" Since the future is async, the Actor could begin processing the next several messages while the future associated with the prior message is still running."). Next, we can pass this future, store it and assign it.
Hope so you understand what I'm trying to say.
Src : https://www.brianstorti.com/the-actor-model/
If you need to mutate state in futures without blocking incoming messages you might want to reconsider redesigning your actor model. I would introduce separate actors for each task you would use those futures on. After all, an actor's main task is to maintain its state without letting it escape thus providing safe concurrency. Define an actor for those long running task whose responsibility is only to take care of that.
Instead of taking care of the state manually you might want to consider using akka's FSM so you get a much cleaner picture of what changes when. I presonally prefer this approach to ugly variables when I'm dealing with more complex systems.

How to organize concurrent request processing in Scala?

Suppose I have a server in Scala, which processes incoming client requests. I have a function def process(req: Request): Response to process requests. Now I would like to process only K requests concurrently and keep M requests in queue.
In Java I would probably create a ThreadPoolExecutor with K threads and a queue of size M. Now I wonder how to do that in Scala with Actors/Futures etc.
If you must have def process(req: Request): Response), then I think your Scala solution may turn out to be similar to Java. If you can have def process(req: Request): Future[Response], the it opens other possibilities.
When using futures, you provide (implicitly or explicitly) an execution context that can be constructed from a Java executor. So you would be able to choose your thread pool size and queue size that way. The benefit of using futures is that you can compose them with map and flatMap and a few other combinators. See http://docs.scala-lang.org/overviews/core/futures.html for more information.
With actors, you have another model of concurrency where you can create K actors. You can have a router that dispatches each request to the actors. Each actor is independently processes the request and sends the Response to whatever needs it when processing is complete. The nice part about actors is that each actor being independent does not typically share anything with other actors, so you don't have to synchronize the code. See http://doc.akka.io/docs/akka/2.1.4/general/terminology.html for more information.
Overall I think Scala can use anything that Java has, and provides more mechanisms to do more complex things.