pub struct TenantRegistry { /* private fields */ }Expand description
Tenant registry with dynamic provisioning.
Hot path: resolve() is one ArcSwap pointer load + an immutable map
read — exactly the zero-lock profile of the old frozen map. Control
plane: Self::upsert/Self::suspend/Self::resume copy-on-write a new snapshot and
swap it atomically, so onboarding a customer (or cutting off a delinquent
one) takes effect on the next request — no redeploy, no restart.
Not #[Injectable] — provide via ctx.provide(TenantRegistry::new(...)).
Implementations§
Source§impl TenantRegistry
impl TenantRegistry
pub fn new( strategy: TenantStrategy, tenants: Vec<TenantConfig>, fallback: Option<TenantId>, ) -> Self
Sourcepub fn upsert(&self, cfg: TenantConfig)
pub fn upsert(&self, cfg: TenantConfig)
Add or replace a tenant — visible to the very next request.
Sourcepub fn suspend(&self, id: &TenantId)
pub fn suspend(&self, id: &TenantId)
Suspend a tenant: resolve() returns None → guards reject with 401.
Deliberately does NOT fall through to the fallback tenant — a
suspended customer must not silently ride the shared pool.
pub fn resume(&self, id: &TenantId)
Sourcepub fn resolve(&self, headers: &HeaderMap) -> Option<Arc<TenantConfig>>
pub fn resolve(&self, headers: &HeaderMap) -> Option<Arc<TenantConfig>>
Resolve the request’s tenant. Called once per request by the boundary.
One atomic snapshot load + immutable map reads — zero locks.
Unknown IDs resolve to the fallback (a typo’d header cannot select an
unconfigured tenant); suspended IDs resolve to None outright.
pub fn get(&self, id: &TenantId) -> Option<Arc<TenantConfig>>
Sourcepub fn resolve_by_id(&self, id: &str) -> Option<Arc<TenantConfig>>
pub fn resolve_by_id(&self, id: &str) -> Option<Arc<TenantConfig>>
Resolve a tenant by its raw id — the non-HTTP twin of
resolve, used by the consumer mesh where the id
rides a message envelope instead of a header. Same semantics:
suspended → None outright (a suspended tenant’s queued events
must stop processing, exactly like its HTTP traffic). Unknown ids get
no fallback: an envelope names its tenant explicitly, and falling
back would process data under the wrong tenant.
Auto Trait Implementations§
impl !Freeze for TenantRegistry
impl RefUnwindSafe for TenantRegistry
impl Send for TenantRegistry
impl Sync for TenantRegistry
impl Unpin for TenantRegistry
impl UnsafeUnpin for TenantRegistry
impl UnwindSafe for TenantRegistry
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> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
Source§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
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