in finagle-core/src/main/scala/com/twitter/finagle/naming/BindingFactory.scala [214:298]
protected[this] def boundPathFilter(path: Path): Filter[Req, Rep, Req, Rep]
def make(
params: Stack.Params,
next: Stack[ServiceFactory[Req, Rep]]
): Stack[ServiceFactory[Req, Rep]] = {
val param.Label(label) = params[param.Label]
val param.Stats(stats) = params[param.Stats]
val param.Timer(timer) = params[param.Timer]
val Dest(dest) = params[Dest]
val LoadBalancerFactory.Param(balancer) = params[LoadBalancerFactory.Param]
val eagerConnections = params[EagerConnections].enabled
val DisplayBoundName(displayFn) = params[DisplayBoundName]
// we check if the stack has been explicitly configured to detect misconfiguration
// and make sure that the underlying balancer supports eagerly connecting to endpoints
val eagerlyConnect: Boolean =
if (params.contains[EagerConnections]) {
if (eagerConnections && !balancer.supportsEagerConnections) {
// misconfiguration
log.warning(
"EagerConnections is only supported for the aperture load balancer. " +
s"stack param found for ${label}.")
false
} else eagerConnections
} else {
eagerConnections && balancer.supportsEagerConnections
}
def newStack(errorLabel: String, bound: Name.Bound) = {
val displayed = displayFn(bound)
val statsWithBoundName = new StatsReceiverProxy {
protected def self: StatsReceiver = stats
override def stat(metricBuilder: MetricBuilder): Stat =
stats.stat(metricBuilder.withIdentifier(Some(displayed)))
override def counter(metricBuilder: MetricBuilder): Counter =
stats.counter(metricBuilder.withIdentifier(Some(displayed)))
override def addGauge(metricBuilder: MetricBuilder)(f: => Float): Gauge =
stats.addGauge(metricBuilder.withIdentifier(Some(displayed)))(f)
override def registerExpression(expr: ExpressionSchema): Try[Unit] =
super.registerExpression(expr.withLabel(ExpressionSchema.ProcessPath, displayed))
}
val updatedParams =
params +
// replace the possibly unbound Dest with the definitely bound
// Dest because (1) it's needed by AddrMetadataExtraction and
// (2) it seems disingenuous not to.
Dest(bound) +
LoadBalancerFactory.Dest(bound.addr) +
LoadBalancerFactory.ErrorLabel(errorLabel) +
param.Stats(statsWithBoundName)
val forceWithDtab: Boolean = params[EagerConnections].withForceDtab
// Explicitly disable `EagerConnections` if (1) `eagerlyConnect` is false, indicating that
// the feature was explicitly disabled or the underlying balancer does not support the eager connections
// feature or (2) If request-level dtab overrides are due to their unpredictable nature,
// resulting in wasteful connections. The second condition applies only if
// EagerConnectionsType.ForceWithDtab is false.
val finalParams =
if (!eagerlyConnect || (!forceWithDtab && !(Dtab.local.isEmpty && Dtab.limited.isEmpty)))
updatedParams + EagerConnections(false)
else updatedParams
val client = next.make(finalParams)
boundPathFilter(bound.path) andThen client
}
val factory = dest match {
case bound @ Name.Bound(_) => newStack(label, bound)
case Name.Path(path) =>
val BaseDtab(baseDtab) = params[BaseDtab]
new BindingFactory(path, newStack(path.show, _), timer, baseDtab, stats.scope("namer"))
}
// if enabled, eagerly bind the name in order to trigger the creation of the load balancer,
// which in turn will eagerly create connections.
if (eagerlyConnect) {
factory().onSuccess(_.close())
}
Stack.leaf(role, factory)
}