pub struct MasterClientPool { /* private fields */ }Expand description
A pool of MasterClients over independent HTTP/2 channels.
§Why
A single tonic Channel multiplexes all RPCs over one HTTP/2 connection,
which caps concurrency at SETTINGS_MAX_CONCURRENT_STREAMS (default 100).
Under 256-way concurrency over remote RTT the surplus requests queue in
tower::Buffer, which is the measured root cause of the remote GetFileStatus
/ OpenFile regression vs Java (Java defaults to a channel pool). Spreading
requests across master_connection_pool_size channels removes the queue.
§Scheduling
Two strategies are available via GoosefsConfig::master_connection_pool_schedule:
- RoundRobin (default): cycles through channels in order. Wait-free, zero overhead, no in-flight tracking required.
- P2C: Power of Two Choices — uniformly samples two distinct channels
with a fast PRNG (
fastrand) and picks the one with fewer in-flight RPCs. Per-channel in-flight counts are tracked inside eachMasterClient(incremented inwith_retry, decremented on RPC completion), so the count is accurate even forMasterClients cloned out of the pool (e.g. byGoosefsFileWriter).
§HA consistency
Every pooled client is constructed with the same inquire_client, so a
failover decision is shared: all channels re-discover and switch to the same
new Primary, eliminating split-brain. Each channel performs its own SASL
handshake and carries a unique channel-id, fully compatible with the
ArcSwap<AuthedState> model.
Implementations§
Source§impl MasterClientPool
impl MasterClientPool
Sourcepub async fn connect_with_inquire(
config: &GoosefsConfig,
inquire_client: Arc<dyn MasterInquireClient>,
) -> Result<Self>
pub async fn connect_with_inquire( config: &GoosefsConfig, inquire_client: Arc<dyn MasterInquireClient>, ) -> Result<Self>
Connect a pool of config.master_connection_pool_size master clients,
all sharing the supplied inquire_client.
The size is clamped to at least 1, so this is a strict superset of the
previous single-channel behaviour (size = 1).
Sourcepub fn pick(&self) -> Arc<MasterClient> ⓘ
pub fn pick(&self) -> Arc<MasterClient> ⓘ
Pick the next client according to the configured scheduling strategy.
RoundRobin(default): cycle through channels in order. Wait-free, zero overhead, no in-flight tracking required.P2C: Power of Two Choices — uniformly sample two distinct channels at random and select the one with fewer in-flight RPCs. The per-channel in-flight count is maintained insideMasterClient::with_retry(not by this method), so it stays accurate even for clients cloned out of the pool.
Returns Arc<MasterClient> — callers interact with it exactly as
before. The in-flight counter lives inside MasterClient itself
(shared via Arc<AtomicUsize> across clones), so P2C load awareness
works regardless of whether the caller holds the Arc directly or
clones the inner MasterClient.
Auto Trait Implementations§
impl !Freeze for MasterClientPool
impl !RefUnwindSafe for MasterClientPool
impl !UnwindSafe for MasterClientPool
impl Send for MasterClientPool
impl Sync for MasterClientPool
impl Unpin for MasterClientPool
impl UnsafeUnpin for MasterClientPool
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request