Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dispatcher configuration for `PoolRouter` in the Akka Typed DSL #28370

Closed
CodeLionX opened this issue Dec 12, 2019 · 3 comments
Closed

Dispatcher configuration for `PoolRouter` in the Akka Typed DSL #28370

CodeLionX opened this issue Dec 12, 2019 · 3 comments

Comments

@CodeLionX
Copy link
Contributor

@CodeLionX CodeLionX commented Dec 12, 2019

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!

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 😃

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.

@johanandren

This comment has been minimized.

Copy link
Member

@johanandren johanandren commented Dec 16, 2019

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

@CodeLionX

This comment has been minimized.

Copy link
Contributor Author

@CodeLionX CodeLionX commented Dec 16, 2019

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:

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

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.

@johanandren

This comment has been minimized.

Copy link
Member

@johanandren johanandren commented Dec 16, 2019

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

CodeLionX added a commit to CodeLionX/akka that referenced this issue Dec 16, 2019
- add withRouteeProps to scaladsl
- add withRouteeProps to javadsl
- use Props.empty as default props for the pool router's routees
CodeLionX added a commit to CodeLionX/akka that referenced this issue Dec 16, 2019
@johanandren johanandren added this to the 2.6.2 milestone Dec 17, 2019
@CodeLionX CodeLionX removed their assignment Dec 17, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.