Akka: Dispatcher configuration for `PoolRouter` in the Akka Typed DSL

Created on 13 Dec 2019  路  3Comments  路  Source: akka/akka

I suggest adding the dispatcher configuration to the current PoolRouter DSL.

I need a pool router to spawn its children with a specific dispatcher, because they perform CPU-heavy computation and should not use the default dispatcher. This is not possible in the current Akka Typed DSL.

API Proposal

I would like to be able to control the used dispatchers explicitly. I could imagine the following extensions of the Pool Router DSL. Other suggestions welcome!

```scala
def heavyLoad: Behavior[Command] = Behaviors.receive{ case (ctx, _: Command) =>
// heavy CPU load for ~1-2s
Behaviors.same
}

val n = _ // max number of cores
val pool: PoolRouter[Command] = Routers
.pool(n)(
Behaviors.supervise(heavyLoad).onFailure(
SupervisorStrategy.restart.withLimit(3, 8 seconds)
)
)
.withRoundRobinRouting()
// 1) my favorable suggestion:
// builder methods with parameter type: akka.actor.typed.DispatcherSelector
.withHeadDispatcher(DispatcherSelector.default())
.withRouteeDispatcher(DispatcherSelector.fromConfig("cpu-bound-dispatcher"))
// 2) or maybe use the more general props wording:
// parameter type: akka.actor.typed.Props
.withProps(DispatcherSelector.default())
.withRouteeProps(DispatcherSelector.fromConfig("cpu-bound-dispatcher"))
```

Alternatives

  • Writing my own router implementation (unfortunately this also includes the routing logic, because they are internal APIs). This means a lot of more work for me, despite that I just need the standard routing logic.
  • Falling back to the more feature-rich Akka classic APIs (not tested like that yet):

    val strategy: SupervisorStrategy = OneForOneStrategy() {
    case _ => SupervisorStrategy.Restart
    }
    
    val router: Props = RoundRobinPool(
    nrOfInstances = n,
    supervisorStrategy = strategy,
    routerDispatcher = Dispatchers.DefaultDispatcherId
    ).props(
    routeeProps = Props[HeavyLoadWorker].withDispatcher("cpu-bound-dispatcher")
    )
    

    I would like to circumvent this, because I would have to make my workers classic actors and the new typed APIs are nicer :smiley:

Unfortunately, I can not use the Group Router, because the code is performance critical and I do not want to send the tasks to all workers across nodes (I also use Akka Cluster Typed), although it supports spawning workers with props.

My environment:

  • Scala 2.13.1
  • "akka-actor-typed" 2.6.0
    Do you need more info?

Do you have any other ideas how to achieve this?
I would be glad to help shaping this idea or submitting a PR with the necessary changes.

3 - in progress help wanted typed

All 3 comments

.withRouteeProps(props) sounds like the right way to do it to me, a PR adding that would be great.

Ok. I will create a PR for it.

My plan is to add the new withRouteeProps(props) to the builder and then change the PoolRouterImpl from:

https://github.com/akka/akka/blob/2ab714cd711cba318cd687ad8ce91b6125b1ee2b/akka-actor-typed/src/main/scala/akka/actor/typed/internal/routing/PoolRouterImpl.scala#L49-L54

to:

private final class PoolRouterImpl[T]( 
     ctx: ActorContext[T], 
     poolSize: Int, 
     behavior: Behavior[T], 
     logic: RoutingLogic[T],
     routeeProps: Option[Props]) 
     extends AbstractBehavior[T](ctx) { 

This means that the default behavior would be the same, and only if one supplies routeeProps, they will be used to spawn the routees.

You can skip having an Option and always have a props and use Props.empty as starting value.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

armanbilge picture armanbilge  路  3Comments

patriknw picture patriknw  路  4Comments

raboof picture raboof  路  3Comments

johanandren picture johanandren  路  3Comments

rrodseth picture rrodseth  路  4Comments