// Copyright 2026 Leo Cheng
// SPDX-License-Identifier: Apache-2.0
///|
/// Which of several pools to one service to take from: two drawn by `first`
/// and `second`, each in `[0, 1)`, and of those the one whose breaker refuses
/// less, then the one with fewer in use.
///
/// Two random choices spread load almost as evenly as scanning every pool,
/// which is why tower's `balance` and Finagle make this choice. `-1` when there
/// are no pools.
pub fn[T] pick(
pools : ArrayView[Pool[T]],
now : Int64,
first~ : Double,
second~ : Double,
) -> Int32 {
let count = pools.length()
if count == 0 {
return -1
}
let a = slot(first, count)
let b = slot(second, count)
let (ra, rb) = (pools[a].refusal(now), pools[b].refusal(now))
if ra != rb {
return if ra < rb { a } else { b }
}
if pools[b].busy() < pools[a].busy() {
b
} else {
a
}
}
///|
/// The share of new connections the ward's breaker is refusing at `now`; zero
/// without a breaker.
pub fn[T] Pool::refusal(self : Pool[T], now : Int64) -> Double {
match self.ward.breaker {
Some(breaker) => breaker.ratio(now)
None => 0.0
}
}
///|
fn slot(draw : Double, count : Int32) -> Int32 {
let at = (draw * count.to_double()).to_int()
if at < 0 {
0
} else if at >= count {
count - 1
} else {
at
}
}