Skip to main content

GraphObserveOne

Struct GraphObserveOne 

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

Single-node observe handle (canonical §3.6.2).

D246: holds a Core-free Graph; &Core is passed per call.

§Two coexisting message-injection shapes (D298, 2026-05-26)

This impl exposes BOTH the canonical up(messages) open-vocab shape AND per-tier typed methods. They have different semantics and are NOT sugar wrappers for each other. Both shapes are supported as first-class public API; users pick based on intent.

  1. Canonical R3.6.2 — Self::up(messages) — send messages UPSTREAM toward the observed node’s sources. Routes through Core::up, which iterates each dep and dispatches the message-specific upstream action (Pause → pause each dep; Resume → resume each dep; Invalidate → recursive plain- forward to leaves per R1.4.2; Teardown → teardown each dep). For a leaf node with no deps (e.g., a state node), up() is a no-op — there is no upstream. Open message vocabulary mirrors pure-ts Node.up(messages) (core/node.ts:1430).

  2. Direct typed methods — Self::pause / Self::resume / Self::invalidate — mutate the OBSERVED NODE directly (not its upstream). observer.pause(lock) calls Core::pause(self.node_id, lock) and pauses the observed node itself; for a leaf state node, this DOES pause it. Rust-idiomatic typed-arg shortcuts for the common “pause/resume/invalidate the thing I’m observing” pattern. Non-allocating (no Vec<Message> heap churn on the control plane). The collaboration directive in feedback_no_imperative user memory favors these intent-named typed calls over message-injection vocabulary when the operation IS “act on this node directly.”

Use up(messages) for canonical upstream-injection (matches TS pure-ts wire shape; required for cross-impl parity scenarios asserting canonical R3.6.2 behavior). Use typed methods for direct-node ergonomic mutation. Same GraphObserveOne handle exposes both.

§Decision provenance

  • Q1 user-locked Option 2 (canonical primary + typed sugar coexisting). Override of D196 (consumer-pressure gate) per the /porting-to-rs clear all the perf items and the deferred items. regardless if they need a valid consumer demand directive.
  • D298 (~/src/graphrefly-ts/docs/rust-port-decisions.md).

Implementations§

Source§

impl GraphObserveOne

Source

pub fn node_id(&self) -> NodeId

The observed NodeId.

Source

pub fn subscribe(&self, core: &Core, sink: Sink) -> ObserveSub

Subscribe a sink. Returns an ObserveSub id pair — detach owner-invoked (D246 rule 3).

Source

pub fn pause(&self, core: &Core, lock: LockId) -> Result<(), PauseError>

Send [PAUSE, lock] upstream.

§Errors

See PauseError.

Source

pub fn resume( &self, core: &Core, lock: LockId, ) -> Result<Option<ResumeReport>, PauseError>

Send [RESUME, lock] upstream.

§Errors

See PauseError.

Source

pub fn invalidate(&self, core: &Core)

Send [INVALIDATE] upstream.

Source

pub fn up(&self, core: &Core, messages: &[Message]) -> Result<(), UpError>

Send messages upstream toward the observed node’s sources (canonical R3.6.2 up(messages) shape — D298, 2026-05-26).

Each message is dispatched via Core::up to the observed node, which then forwards per the tier-specific upstream routing:

  • Message::Pause(lock)Core::pause on each dep.
  • Message::Resume(lock)Core::resume on each dep.
  • Message::Invalidate → recursive plain-forward to leaf sources per R1.4.2 (no self-process at intermediates).
  • Message::TeardownCore::teardown cascade on each dep.
  • Message::Start / Message::Dirty → no-op upstream per the routing table in Core::up.

For a leaf node (no deps — e.g., a state node) up() is a no-op. Use the typed Self::pause / Self::resume / Self::invalidate methods if the intent is to mutate the observed node directly.

Fails on the first message that errors; subsequent messages are NOT dispatched. Empty messages is Ok(()).

§Errors
  • UpError::UnknownNode — observed node not registered (only reachable if teardown removed it after observe()).
  • UpError::TierForbiddenmessages contains a tier-3 (Data/Resolved) or tier-5 (Complete/Error) variant; these are downstream-only per R1.4.1.
Source

pub fn graph(&self) -> &Graph

The backing graph handle.

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.

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

Source§

type Output = T

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