Skip to main content

AtlasRegistry

Struct AtlasRegistry 

Source
pub struct AtlasRegistry { /* private fields */ }
Expand description

In-memory state shared by all gRPC handlers (new + legacy). All ops go through one of the typed async methods below. Arc<AtlasRegistry> is cheap to clone; the interior RwLock serialises mutations.

contracts is loaded once at startup from <robonix_source>/capabilities/** and is read-only for the lifetime of the process — handlers serve QueryContract / ListContracts directly off it without locking.

Implementations§

Source§

impl AtlasRegistry

Source

pub fn with_contracts(contracts: ContractRegistry) -> Self

Construct a registry with an empty capability/channel state plus a pre-loaded contract registry. Use this from main.rs once the capabilities dir has been resolved.

Source

pub fn contracts(&self) -> &ContractRegistry

Source§

impl AtlasRegistry

Source

pub fn now_ms() -> u64

Source

pub async fn register( &self, provider_id: &str, kind: Kind, namespace: &str, capability_md_path: &str, ) -> Result<String, Status>

Register a new capability instance, OR take over an existing provider_id slot whose previous provider is gone. Empty provider_id triggers Atlas-assigned ephemeral id. Returns the resolved id.

Takeover semantics — a re-Register on an existing provider_id is NOT an error. We assume the old process is dead (or about to be), so we drop its endpoints + state and reset last_heartbeat to now. The caller is then expected to redeclare capabilities with its own fresh endpoints. Without this, an orphan provider (heartbeat eviction hasn’t fired yet — 60s default) blocks every subsequent boot of the same package: rbnx waits for a “new” provider to appear in atlas, the python framework only retries register once and then quietly keeps going, and atlas keeps pointing consumers at the dead process’s endpoints. The previous “ALREADY_EXISTS” failure mode caught accidental dual deployments but the cure was worse than the disease — silent boot failures are nearly impossible to diagnose. If two live processes claim the same id, both will heartbeat into the same record and the latest declare wins; that case shows up as scattered/mysterious endpoint flips, which is at least visible.

Source

pub async fn unregister(&self, provider_id: &str) -> bool

Idempotent: returns true if a record was removed, false if the id was unknown. Also drops any channels where this provider was the provider — consumers will get NOT_FOUND on their next call and can re-discover.

Source

pub async fn set_lifecycle_state( &self, provider_id: &str, new_state: LifecycleState, detail: &str, ) -> Result<LifecycleState, Status>

Update the provider’s lifecycle state. Returns the previous value (or the inferred fallback when nothing’s been pushed yet) so callers can log “X went INACTIVE → ACTIVE” without a separate query. Validation is soft: illegal transitions log a warn but the new state is still stored. Strict validation will land later once telemetry confirms there are no spurious illegal transitions during atlas/provider startup-race conditions.

Source

pub async fn heartbeat(&self, provider_id: &str) -> Result<u64, Status>

Updates last_heartbeat_ms to now. Returns the timestamp it set.

Source

pub async fn declare( &self, provider_id: &str, contract_id: &str, transport: Transport, proposed: &str, params: TransportParams, description: &str, ) -> Result<String, Status>

Declare ONE transport for ONE contract on a registered provider. Returns the authoritative endpoint string (may differ from proposed when Atlas rewrote it to disambiguate on a mintable transport).

Source

pub async fn query( &self, provider_id: &str, kind: Kind, contract: &str, transport: Transport, ) -> Vec<CapabilityProvider>

Snapshot of registered Providers matching the given filters. Empty provider_id / empty contract / Transport::Unspecified / Kind::Unspecified mean “no filter on that field”. Each returned record carries only the Capabilities that satisfy the contract + transport filters.

Source

pub async fn query_with_prefix( &self, provider_id: &str, kind: Kind, contract: &str, namespace_prefix: &str, transport: Transport, ) -> Vec<CapabilityProvider>

Source

pub async fn connect( &self, consumer_id: &str, provider_id: &str, contract_id: &str, transport: Transport, ) -> Result<(String, String, TransportParams), Status>

Open a channel to one (provider provider, contract, transport). Atlas only providers the edge — the consumer dials the returned endpoint itself (each transport has its own connect protocol; atlas can’t dial generically). Returns the allocated channel handle and the full binding the consumer needs.

Source

pub async fn disconnect(&self, channel_id: &str) -> bool

Idempotent: returns true if a channel was removed, false if the id was unknown (already released, or auto-dropped when its provider went away).

Source

pub async fn capability_md(&self, provider_id: &str) -> Result<String, Status>

Read the provider’s CAPABILITY.md content. Returns “” when the provider registered without a path.

Source

pub async fn inspect_json(&self) -> Result<String, Status>

Debug-only JSON dump of the entire registry. Schema is unstable.

Trait Implementations§

Source§

impl Debug for AtlasRegistry

Source§

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

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

impl Default for AtlasRegistry

Source§

fn default() -> AtlasRegistry

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

Auto Trait Implementations§

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.

§

impl<T> IntoRequest<T> for T

§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
§

impl<L> LayerExt<L> for L

§

fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>
where L: Layer<S>,

Applies the layer to a service and wraps it in [Layered].
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