in finagle-core/src/main/scala/com/twitter/finagle/naming/NameTreeFactory.scala [38:106]
def apply[Key, Req, Rep](
path: Path,
tree: NameTree[Key],
factoryCache: ServiceFactoryCache[Key, Req, Rep],
rng: Rng = Rng.threadLocal
): ServiceFactory[Req, Rep] = {
lazy val noBrokersAvailableFactory = Failed(new NoBrokersAvailableException(path.show))
case class Failed(exn: Throwable) extends ServiceFactory[Req, Rep] {
val service: Future[Service[Req, Rep]] = Future.exception(exn)
def apply(conn: ClientConnection) = service
override def status = Status.Closed
def close(deadline: Time) = Future.Done
}
case class Leaf(key: Key) extends ServiceFactory[Req, Rep] {
def apply(conn: ClientConnection) = factoryCache.apply(key, conn)
override def status = factoryCache.status(key)
def close(deadline: Time) = Future.Done
}
case class Weighted(drv: Drv, factories: Seq[ServiceFactory[Req, Rep]])
extends ServiceFactory[Req, Rep] {
def apply(conn: ClientConnection) = {
Contexts.local.get(CustomNameTreeFactoryKey) match {
case None => factories(drv(rng)).apply(conn)
case Some(l: Long) => factories(drv(Rng(l))).apply(conn)
}
}
override def status = Status.worstOf[ServiceFactory[Req, Rep]](factories, _.status)
def close(deadline: Time) = Future.Done
}
// We want to keep a sub tree in a union if it is reachable
// or if it's explicitly weighted more than 0 and we are configured
// to retain unreachable subtrees (default True)
def shouldKeepInUnion(t: NameTree.Weighted[Key]): Boolean = {
t.tree match {
case NameTree.Neg | NameTree.Fail | NameTree.Empty =>
retainUnreachableUnionBranches() && t.weight > 0.0
case _ => true
}
}
def factoryOfTree(tree: NameTree[Key]): ServiceFactory[Req, Rep] =
tree match {
case NameTree.Neg | NameTree.Fail | NameTree.Empty => noBrokersAvailableFactory
case NameTree.Leaf(key) => Leaf(key)
// it's an invariant of Namer.bind that it returns no Alts
case NameTree.Alt(_*) => Failed(new IllegalArgumentException("NameTreeFactory"))
case NameTree.Union(weightedTrees @ _*) =>
val (weights, trees) = weightedTrees
.filter(shouldKeepInUnion)
.unzip { case NameTree.Weighted(w, t) => (w, t) }
if (weights.isEmpty) {
noBrokersAvailableFactory
} else {
Weighted(Drv.fromWeights(weights), trees.map(factoryOfTree))
}
}
factoryOfTree(tree)
}