Merge pull request #18260 from akka/wip-15040-ScatterGatherFirstCompleted-patriknw
=act #15040 ScatterGatherFirstCompleted reply when no routees
This commit is contained in:
commit
1732e62d0c
2 changed files with 35 additions and 15 deletions
|
|
@ -10,6 +10,9 @@ import akka.actor.{ Props, Actor }
|
||||||
import akka.pattern.ask
|
import akka.pattern.ask
|
||||||
import akka.testkit.{ TestLatch, ImplicitSender, DefaultTimeout, AkkaSpec }
|
import akka.testkit.{ TestLatch, ImplicitSender, DefaultTimeout, AkkaSpec }
|
||||||
import akka.actor.ActorSystem
|
import akka.actor.ActorSystem
|
||||||
|
import akka.actor.Status
|
||||||
|
import java.util.concurrent.TimeoutException
|
||||||
|
import akka.testkit.TestProbe
|
||||||
|
|
||||||
object ScatterGatherFirstCompletedSpec {
|
object ScatterGatherFirstCompletedSpec {
|
||||||
class TestActor extends Actor {
|
class TestActor extends Actor {
|
||||||
|
|
@ -86,4 +89,15 @@ class ScatterGatherFirstCompletedSpec extends AkkaSpec with DefaultTimeout with
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"Scatter-gather pool" must {
|
||||||
|
|
||||||
|
"without routees should reply immediately" in {
|
||||||
|
val probe = TestProbe()
|
||||||
|
val router = system.actorOf(ScatterGatherFirstCompletedPool(nrOfInstances = 0, within = 5.seconds).props(Props.empty))
|
||||||
|
router.tell("hello", probe.ref)
|
||||||
|
probe.expectMsgType[Status.Failure](2.seconds).cause.getClass should be(classOf[TimeoutException])
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ import akka.util.Timeout
|
||||||
import akka.util.Helpers.ConfigOps
|
import akka.util.Helpers.ConfigOps
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import akka.actor.ActorSystem
|
import akka.actor.ActorSystem
|
||||||
|
import scala.concurrent.Future
|
||||||
|
import java.util.concurrent.TimeoutException
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Broadcasts the message to all routees, and replies with the first response.
|
* Broadcasts the message to all routees, and replies with the first response.
|
||||||
|
|
@ -31,8 +33,7 @@ import akka.actor.ActorSystem
|
||||||
@SerialVersionUID(1L)
|
@SerialVersionUID(1L)
|
||||||
final case class ScatterGatherFirstCompletedRoutingLogic(within: FiniteDuration) extends RoutingLogic {
|
final case class ScatterGatherFirstCompletedRoutingLogic(within: FiniteDuration) extends RoutingLogic {
|
||||||
override def select(message: Any, routees: immutable.IndexedSeq[Routee]): Routee =
|
override def select(message: Any, routees: immutable.IndexedSeq[Routee]): Routee =
|
||||||
if (routees.isEmpty) NoRoutee
|
ScatterGatherFirstCompletedRoutees(routees, within)
|
||||||
else ScatterGatherFirstCompletedRoutees(routees, within)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -42,20 +43,25 @@ final case class ScatterGatherFirstCompletedRoutingLogic(within: FiniteDuration)
|
||||||
private[akka] final case class ScatterGatherFirstCompletedRoutees(
|
private[akka] final case class ScatterGatherFirstCompletedRoutees(
|
||||||
routees: immutable.IndexedSeq[Routee], within: FiniteDuration) extends Routee {
|
routees: immutable.IndexedSeq[Routee], within: FiniteDuration) extends Routee {
|
||||||
|
|
||||||
override def send(message: Any, sender: ActorRef): Unit = {
|
override def send(message: Any, sender: ActorRef): Unit =
|
||||||
implicit val ec = ExecutionContexts.sameThreadExecutionContext
|
if (routees.isEmpty) {
|
||||||
implicit val timeout = Timeout(within)
|
implicit val ec = ExecutionContexts.sameThreadExecutionContext
|
||||||
val promise = Promise[Any]()
|
val reply = Future.failed(new TimeoutException("Timeout due to no routees"))
|
||||||
routees.foreach {
|
reply.pipeTo(sender)
|
||||||
case ActorRefRoutee(ref) ⇒
|
} else {
|
||||||
promise.tryCompleteWith(ref.ask(message))
|
implicit val ec = ExecutionContexts.sameThreadExecutionContext
|
||||||
case ActorSelectionRoutee(sel) ⇒
|
implicit val timeout = Timeout(within)
|
||||||
promise.tryCompleteWith(sel.ask(message))
|
val promise = Promise[Any]()
|
||||||
case _ ⇒
|
routees.foreach {
|
||||||
}
|
case ActorRefRoutee(ref) ⇒
|
||||||
|
promise.tryCompleteWith(ref.ask(message))
|
||||||
|
case ActorSelectionRoutee(sel) ⇒
|
||||||
|
promise.tryCompleteWith(sel.ask(message))
|
||||||
|
case _ ⇒
|
||||||
|
}
|
||||||
|
|
||||||
promise.future.pipeTo(sender)
|
promise.future.pipeTo(sender)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue