ClientPool

Struct ClientPool 

Source
pub struct ClientPool<P: Protocol> { /* private fields */ }
Expand description

Concurrent pool of linked clients for one [Protocol].

Provides async access to the underlying map via an internal [tokio::sync::Mutex]. The reverse index (by_module) is kept in lockstep with the primary map so fan-out can enumerate members of a module in O(module members) without scanning every client.

Implementations§

Source§

impl<P: Protocol> ClientPool<P>

Source

pub fn new() -> Self

Create an empty pool.

Source

pub async fn insert(&self, peer: SocketAddr, handle: ClientHandle<P>)

Insert a client handle keyed by peer address.

If the handle already has a module set, the reverse index is updated to include this peer under that module.

§Cancellation safety

This method is not cancel-safe. It takes two internal mutex locks in sequence: dropping the future between the first and second lock().await leaves the forward map updated but the reverse module index stale. The only correct recovery is to call Self::remove for the same peer and retry.

Source

pub async fn remove(&self, peer: &SocketAddr) -> Option<ClientHandle<P>>

Remove a client by peer address, returning the handle if present.

§Cancellation safety

This method is not cancel-safe for the same reason as Self::insert — it touches the forward and reverse maps in sequence and cancellation between the two awaits leaves a stale module-index entry.

Source

pub async fn set_module(&self, peer: &SocketAddr, module: Module)

Attach a peer to a module, updating both the handle and the reverse index.

No-op if the peer is not in the pool. If the peer was already attached to a different module, the old entry is removed.

§Cancellation safety

This method is not cancel-safe. See Self::insert for the dual-lock sequencing rationale.

Source

pub async fn members_of_module(&self, module: Module) -> Vec<SocketAddr>

Enumerate the peers currently linked to the given module.

§Cancellation safety

This method is cancel-safe. It acquires a single mutex lock and clones the membership set; dropping the future either before or after the clone leaves the pool state unchanged.

Source

pub async fn len(&self) -> usize

Number of clients currently in the pool.

§Cancellation safety

This method is cancel-safe. It takes a single mutex lock and reads a usize; no mutation occurs.

Source

pub async fn is_empty(&self) -> bool

Whether the pool is empty.

§Cancellation safety

This method is cancel-safe. See Self::len.

Source

pub async fn contains(&self, peer: &SocketAddr) -> bool

Whether the pool contains a handle for the given peer.

§Cancellation safety

This method is cancel-safe. See Self::len.

Source

pub async fn mark_unhealthy(&self, peer: &SocketAddr) -> UnhealthyOutcome

Increment the send-failure counter on a peer and report whether the peer should now be evicted.

Returns UnhealthyOutcome::StillHealthy with failure_count 0 if the peer is not present — callers should treat that as “no increment happened” rather than “counter reset”.

The eviction threshold is DEFAULT_UNHEALTHY_THRESHOLD. Once failure_count >= threshold the return value switches to UnhealthyOutcome::ShouldEvict and stays there on every subsequent increment until the caller actually removes the peer.

§Cancellation safety

This method is cancel-safe. Only a single mutex lock is taken and the mutation is committed before drop(clients) releases the lock; dropping the future after that point has no effect on pool state.

Source

pub async fn record_last_heard(&self, peer: &SocketAddr, now: Instant)

Record that we just received a datagram from the given peer.

§Cancellation safety

This method is cancel-safe. See Self::mark_unhealthy.

Source

pub async fn module_of(&self, peer: &SocketAddr) -> Option<Module>

Look up the module a peer is currently linked to, if any.

§Cancellation safety

This method is cancel-safe. See Self::len.

Source

pub async fn access_of(&self, peer: &SocketAddr) -> Option<AccessPolicy>

Look up the AccessPolicy for a peer, if any.

Returns None if the peer is not in the pool. Used by the endpoint to gate voice-frame forwarding for AccessPolicy::ReadOnly clients.

§Cancellation safety

This method is cancel-safe. See Self::len.

Source

pub async fn try_consume_tx_token( &self, peer: &SocketAddr, now: Instant, ) -> bool

Attempt to consume one TX-budget token from the given peer.

Returns true on success (the fan-out engine may send this frame to the peer); returns false if the bucket is empty (the frame must be dropped for this peer). Returns false if the peer is not in the pool — no handle means no budget.

The now argument is the caller’s injected wall-clock instant and is used to drive the token bucket’s refill bookkeeping. The method never calls Instant::now itself, matching the sans-io rate-limiter pattern.

§Cancellation safety

This method is cancel-safe. Only a single mutex lock is taken and the bucket mutation is committed before the lock is released.

Source

pub async fn with_handle_mut<F, R>(&self, peer: &SocketAddr, f: F) -> Option<R>
where F: FnOnce(&mut ClientHandle<P>) -> R,

Run a closure with exclusive access to a peer’s handle.

Holds the internal Mutex for the duration of the closure; keep the body short and avoid blocking operations inside it. Returns None if no handle exists for the given peer (the closure is not invoked in that case).

§Cancellation safety

This method is cancel-safe before the lock is acquired and after the closure returns. While the closure is executing it runs synchronously under the lock, so cancellation during f is not possible. Do not call .await inside f or this guarantee is lost.

Trait Implementations§

Source§

impl<P: Debug + Protocol> Debug for ClientPool<P>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<P: Protocol> Default for ClientPool<P>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<P> !Freeze for ClientPool<P>

§

impl<P> !RefUnwindSafe for ClientPool<P>

§

impl<P> Send for ClientPool<P>

§

impl<P> Sync for ClientPool<P>

§

impl<P> Unpin for ClientPool<P>

§

impl<P> !UnwindSafe for ClientPool<P>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more