Skip to main content

Context

Struct Context 

Source
pub struct Context {
Show 13 fields pub index: Arc<Index>, pub registry: Arc<CapabilityRegistry>, pub peers: Arc<PeerBoard>, pub episodes: Arc<EpisodeBoard>, pub why: Arc<Catalogue>, pub product: Arc<ProductModel>, pub executor: Arc<CapabilityExecutor>, pub caller: Option<PeerId>, pub executions: Arc<ExecutionEngine>, pub progress: Progress, pub web: Arc<Topology>, pub mesh: Arc<MeshRuntime>, pub reading: u64,
}
Expand description

What a handler may read: the index of the repository, the registry it belongs to, the board of peers attached to this process, and, when the call came through an MCP session, which peer made it. Index and registry are immutable for the life of a process; the board is the one thing that changes, and it lives in memory only.

Fields§

§index: Arc<Index>

The index of the repository’s objects.

§registry: Arc<CapabilityRegistry>

The registry the handler belongs to, for introspection capabilities.

§peers: Arc<PeerBoard>

The peers attached to this process.

§episodes: Arc<EpisodeBoard>

The execution episodes this process holds: one per client that asked for one, keyed by the client’s own durable identity and driven by the connection (ADR 0103).

Beside the peer board and not inside it, because a peer and an episode are not the same thing: a connection holds zero or one episode, and an episode outlives the connection that opened it so that a client which reconnects comes back to its own.

§why: Arc<Catalogue>

The Why catalogue, derived from the index once when this context is composed and shared by every projection that reads it. A request never rebuilds it.

§product: Arc<ProductModel>

The product model: the features of the layer with every fact a surface may say about them derived from the registry, the index, the catalogue and the topology. Built once, after the three it reads, and shared the same way.

§executor: Arc<CapabilityExecutor>

The one execution path: counters, cache, handler dispatch. Shared by every transport and every session of this process.

§caller: Option<PeerId>

The peer this call came from, when it came through an MCP session; None for the command line and for a plain HTTP request.

§executions: Arc<ExecutionEngine>

The executions this process is running, and the engine that starts them.

One per process, so that an execution started from a browser is the same execution an MCP client asks about and the command line lists. A handler reads it only when it is itself the execution plane’s own capability; every other handler reports through Context::progress and never learns whether anything was listening.

§progress: Progress

What this call reports its steps and progress to, and how it learns it should stop.

Silent unless the call came through the execution engine, which is why a handler may report unconditionally and a benchmark sample costs nothing.

§web: Arc<Topology>

The repository’s web surfaces, resolved once for this process.

Resolved here and never again: a projection that serves a subset of it narrows this value rather than discovering its own, so what the HTTP router serves, what the home page lists and what web.surfaces answers are three readings of one resolution.

§mesh: Arc<MeshRuntime>

The mesh runtime: the discovered nodes of this process, and the machinery that observes them. Inactive (an empty registry with a reason) until a shared server activates it from the repository’s mesh declaration; the capabilities of the mesh module are its projections.

§reading: u64

Which reading of the repository this is: a number no other Context::new of this process was given, shared by every view of it (Context::for_caller, Context::reporting, Context::with_web). A reload is a new reading. It is what a crate::capability::CachePolicy::Generation entry is kept under, because the registry fingerprint covers what is declared and not the git state an index was read at.

Implementations§

Source§

impl Context

Source

pub fn new(index: Arc<Index>, registry: Arc<CapabilityRegistry>) -> Self

A context over an index and a registry, with an empty board, a fresh executor and no caller.

Source

pub fn continuing(&self, previous: &Context) -> Self

This context’s reading of the repository, carrying on the in-memory life of an earlier one: what crate::live::Live hands out after the repository has moved.

A reload is not a restart. The index, the registry and everything derived from them — the Why catalogue, the product model, the web topology — are pictures of the repository and are replaced wholesale, which is the point. The peer board, the executions this process is running, the episodes its clients opened and the capability executor are not pictures of anything: they are this process’s own life, and a peer that announced its intent must not vanish from the board because somebody else committed. The executor is carried because its cache is keyed by the registry’s fingerprint, so the entries of an older generation are already unreachable and the ones of an unchanged capability are still worth having.

let renewed = after.continuing(&before);
assert!(Arc::ptr_eq(&renewed.peers, &before.peers), "the board survives a reload");
assert!(Arc::ptr_eq(&renewed.episodes, &before.episodes), "so do the episodes");
assert!(Arc::ptr_eq(&renewed.index, &after.index), "the picture does not");
Source

pub fn for_caller(&self, caller: PeerId) -> Self

The same context, seen from one peer: what a session hands its handlers.

Source

pub fn reporting(&self, progress: Progress) -> Self

The same context, seen by one execution: what the engine hands the handler it runs.

Everything else is shared, the engine included, so a capability that reads the executions of this process sees its own while it runs.

Source

pub fn with_web(&self, web: Arc<Topology>) -> Self

The same context with the web topology narrowed to what one projection serves.

The narrowing is a filter over the value this context already holds, never a second discovery: a projection cannot serve a surface the process did not resolve.

Source

pub fn execute(&self, id: &str, input: Value) -> Result<Value, CapabilityError>

Execute a capability by id: the one way anything calls a handler.

Source

pub fn execute_observed( &self, id: &str, input: Value, ) -> Result<Value, CapabilityError>

The same, with the cache stepped over: what an execution runs.

See CapabilityExecutor::execute_uncached for why watching something happen and being handed a remembered answer are not the same request.

Source

pub fn read(&self, id: &str, input: Value) -> Latest

The latest reading of a capability, at once, with how old it is: what a page shows.

Never an answer: see crate::capability::readings for what it is instead, and what it costs.

use majordomus_cli::capability::readings::Freshness;
use majordomus_cli::synthetic::SyntheticRepository;

let repo = SyntheticRepository::small().unwrap();
let ctx = repo.context().unwrap();
let reading = ctx.read("plan.status", serde_json::json!({}));
// a first reading is waited for, so it holds what `execute` answers, and says how it
// stands: read just now, in the repository as it is
assert_eq!(reading.value.ok(), ctx.execute("plan.status", serde_json::json!({})).ok());
assert_eq!(reading.freshness, Freshness::Current);
assert!(reading.age.is_some());

Trait Implementations§

Source§

impl Clone for Context

Source§

fn clone(&self) -> Context

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

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
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

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.

§

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> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
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 = 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