Skip to main content

Context

Struct Context 

Source
pub struct Context { /* private fields */ }

Implementations§

Source§

impl Context

Source

pub fn builder(node_id: impl Into<String>) -> ContextBuilder

Create a context builder

Shorthand for ContextBuilder::new(node_id).

§Example
let ctx = Context::builder("my-node")
    .with_instance("instance-1")
    .build()
    .await?;
Source§

impl Context

Source

pub fn get_redis_url() -> Result<String>

Get Redis URL from infrastructure configuration

Source

pub fn get_control_plane_redis_url() -> Result<Option<String>>

Get control plane Redis URL from infrastructure configuration

Source§

impl Context

Source

pub async fn new(node_id: &str) -> Result<Self>

Create a new context

§Arguments
  • node_id - Unique identifier for this node (fallback if NODE_NAME env var not set)
§Environment Variables
  • NODE_NAME - If set, overrides the node_id parameter. This allows node-runner to set full identifiers like @mecha10/speaker for consistent naming across the CLI, dashboard, and health reporting.
§Example
let ctx = Context::new("my-node").await?;
Source

pub fn with_instance(self, instance: &str) -> Self

Set an instance name for this context (builder pattern)

This allows the same node implementation to run multiple instances with different names. The node_id becomes “{node_name}/{instance}”.

§Example
// Single instance (no instance name)
let ctx = Context::new("camera_fake").await?;
// node_id: "camera_fake"

// Multi-instance (with instance names)
let left_ctx = Context::new("camera_fake").await?.with_instance("left");
// node_id: "camera_fake/left"

let right_ctx = Context::new("camera_fake").await?.with_instance("right");
// node_id: "camera_fake/right"
Source

pub fn instance(&self) -> Option<&str>

Get the instance name if set

Returns None for single-instance nodes, or Some(instance) for multi-instance nodes.

Source

pub fn node_id(&self) -> &str

Get the node ID

Source

pub async fn is_shutdown(&self) -> bool

Check if shutdown has been requested

Source

pub async fn shutdown(&self)

Request shutdown

Source

pub async fn wait_for_shutdown(&self)

Wait for shutdown signal

Source

pub fn logging_span(&self) -> Span

Enter a logging span with this node’s context

This returns a guard that, when entered, adds the node_id to all log messages. The span is automatically exited when the guard is dropped.

§Example
use mecha10_core::prelude::*;

let _guard = ctx.logging_span().entered();
info!("This message includes node_id automatically");
debug!("So does this one");
Source§

impl Context

Source

pub async fn load_node_config<T>(&self, node_name: &str) -> Result<T>

Load node configuration with environment-aware file-level fallback

This method implements the V2 configuration system with:

Tier order (mirrors mecha10_cli_core::paths::config::node_config_candidates, the canonical 2-tier resolution order for node configs – this method can’t call that helper directly since mecha10-core is a dependency of mecha10-cli-core, not the reverse, but it must stay in sync with it):

  1. configs/nodes/@mecha10/{node_name}/config.json - Framework nodes
  2. configs/nodes/{node_name}/config.json - Project nodes (preferred)
  3. T::default() - Default implementation, if neither tier has a config file (or no project root could be found)

Environment Detection:

  • Uses MECHA10_ENV env var (default: “dev”)
  • Supported values: “dev”, “staging”, “production”, or custom

Semantic Validation:

  • Not run here. This method is generic over T with only a DeserializeOwned + Default bound, and stable Rust has no specialization – a function generic over T can’t conditionally call crate::config::Validate::validate only when T happens to implement it. Node types that need semantic validation should call validate() explicitly on the config returned here.
§Type Parameters
  • T - Configuration type that implements DeserializeOwned + Default
§Arguments
  • node_name - Name of the node (e.g., “simulator”, “camera-streamer”)
§Returns

The loaded configuration of type T, using the first available source in the fallback chain.

§Example
use mecha10_core::prelude::*;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Deserialize, Serialize, Default)]
struct SimBridgeConfig {
    camera_width: u32,
    camera_height: u32,
    camera_fps: u32,
}

let config: SimBridgeConfig = ctx.load_node_config("simulator").await?;
Source

pub async fn load_node_config_for_instance<T>( &self, node_name: &str, instance_id: Option<&str>, ) -> Result<T>

Like Self::load_node_config, but with an explicit instance_id instead of this context’s own Self::instance.

Node-runner (the supervisor process) is the main reason this is split out: it loads a node’s config.json on that node’s behalf, through a context that represents node-runner itself (not the node), so it can’t rely on self.instance() - it passes the target node’s --instance-id through explicitly instead. Every actual node binary (via node_main!/#[derive(Node)]) should just call Self::load_node_config, which already does the right thing from its own instance().

§Instance-Keyed Config Files

For a multi-instance node (two camera nodes - one real, one simulated - both declared in mecha10.json via the {"name": "@mecha10/camera", "instance_id": "real"} node-list entry shape, LAB-4131), the resolved config file’s per-environment section may itself be a flat config object (today’s behavior, unchanged, used when instance_id is None) or a JSON object keyed by instance id:

{
  "dev": {
    "real": { "source": { "type": "v4l2", "device_path": "/dev/video0" }, "id": "real" },
    "sim":  { "source": { "type": "redis", "topic": "/camera/sim/raw" }, "id": "sim" }
  }
}

When instance_id is Some(id), the sub-object at that key is used as the node’s config (same shape/validation as today’s flat config). An instance_id that isn’t present as a key is an error, rather than silently falling back to T::default() - a multi-instance node whose config is missing an instance’s entry has a real misconfiguration, not an absent config file.

Source

pub async fn load_and_validate_node_config<T>( &self, node_name: &str, ) -> Result<T>

Same as Self::load_node_config, but also validates the loaded JSON against T’s own schemars-derived JSON Schema before deserializing into it (LAB-4066).

This is the load-at-startup counterpart to mecha10_core::schema_validation’s preflight validation (validate_project_config/mecha10 config validate), using the same “every node supplies its own schema” principle that validation’s declared-schema lookup is built on – except here there is no lookup and no “missing schema” case to hard-error on: T: JsonSchema means T’s own derived schema always exists, enforced by the type system at compile time rather than by a runtime registry/convention check. node_main! and #[derive(Node)]’s generated run() call this (not Self::load_node_config) so every node – built-in or custom – gets this check for free the moment its Config struct derives JsonSchema (already required to export a schema for it at all, see mecha10-schema-registry).

Not used for Self::load_node_config callers that read another node’s config file generically through a deliberately-partial/lenient struct (e.g. mecha10-node-runner’s launcher-level NodeConfig) – validating a partial struct’s derived schema against another node’s full config would reject fields the reader never claimed to model, which isn’t this node’s schema to enforce.

§Errors

Returns an error if the config file exists but fails to parse, fails schema validation, or fails to deserialize into T.

Source§

impl Context

Source

pub async fn state_manager(&self) -> Result<Arc<ConcreteStateManager>>

Get or create a state manager for this node

The state manager provides persistent storage for node state across restarts. By default, it uses filesystem storage in ./state/ directory.

§Example
use mecha10_core::prelude::*;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
struct MyState {
    counter: u64,
    position: (f64, f64),
}

let state_mgr = ctx.state_manager().await?;

// Load previous state
let mut state = state_mgr
    .load::<MyState>("my_node")
    .await?
    .unwrap_or(MyState {
        counter: 0,
        position: (0.0, 0.0),
    });

// Update state
state.counter += 1;

// Save state
state_mgr.save("my_node", &state).await?;
Source

pub async fn set_state_manager(&self, manager: Arc<ConcreteStateManager>)

Set a custom state manager for this context

This allows using alternative backends (Redis, PostgreSQL, etc.) or custom implementations.

§Example
use mecha10_core::prelude::*;
use mecha10_core::state::ConcreteStateManager;
use std::sync::Arc;

// Use in-memory state manager for testing
let mem_mgr = Arc::new(ConcreteStateManager::Memory(MemoryStateManager::new()));
ctx.set_state_manager(mem_mgr).await;

Trait Implementations§

Source§

impl AuthExt for Context

Source§

async fn register_policy(&self, policy: &Policy) -> Result<()>

Register a policy Read more
Source§

async fn get_policy(&self, role: &str) -> Result<Option<Policy>>

Get a policy by role name Read more
Source§

async fn list_policies(&self) -> Result<Vec<Policy>>

List all registered policies
Source§

async fn assign_role(&self, node_id: &str, role: &str) -> Result<()>

Assign a role to a node Read more
Source§

async fn get_role(&self, node_id: &str) -> Result<Option<String>>

Get the role assigned to a node Read more
Source§

async fn check_permission( &self, node_id: &str, permission: Permission, topic: &str, ) -> Result<bool>

Check if a node has permission to perform an action on a topic Read more
Source§

async fn delete_policy(&self, role: &str) -> Result<()>

Delete a policy Read more
Source§

async fn unassign_role(&self, node_id: &str) -> Result<()>

Remove role assignment from a node Read more
Source§

impl Clone for Context

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl SchemaRegistryExt for Context

Source§

async fn register_schema(&self, schema: &MessageSchema) -> Result<()>

Register a schema in the registry Read more
Source§

async fn get_schema( &self, name: &str, version: u32, ) -> Result<Option<MessageSchema>>

Get a specific version of a schema Read more
Source§

async fn get_latest_schema(&self, name: &str) -> Result<Option<MessageSchema>>

Get the latest version of a schema Read more
Source§

async fn list_schemas(&self) -> Result<Vec<MessageSchema>>

List all registered schemas (returns latest version of each)
Source§

async fn get_schema_versions(&self, name: &str) -> Result<Vec<MessageSchema>>

Get all versions of a schema Read more
Source§

async fn delete_schema(&self, name: &str, version: Option<u32>) -> Result<()>

Delete a schema version Read more
Source§

impl SchemaVersioningExt for Context

Source§

async fn check_compatibility( &self, name: &str, old_version: u32, new_version: u32, mode: CompatibilityMode, ) -> Result<CompatibilityCheck>

Check compatibility between two schema versions
Source§

async fn register_versioned_schema( &self, schema: &MessageSchema, mode: CompatibilityMode, ) -> Result<CompatibilityCheck>

Register a new schema version with compatibility check
Source§

async fn get_version_info( &self, name: &str, ) -> Result<Option<MessageVersionInfo>>

Get version info for a message type
Source§

async fn deprecate_version( &self, name: &str, version: u32, message: String, ) -> Result<()>

Mark a schema version as deprecated
Source§

async fn is_version_deprecated(&self, name: &str, version: u32) -> Result<bool>

Check if using a deprecated version

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

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

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

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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

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

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

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

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

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.
Source§

impl<T> WithSubscriber for T

Source§

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
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

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