Plan

Struct Plan 

Source
pub struct Plan {
    pub nodes: Vec<Node>,
    pub constants: BTreeMap<OpId, Core>,
    pub root: OpId,
    pub state: OpId,
    pub session: OpId,
    pub presence: OpId,
    pub awareness: OpId,
    pub signals: Vec<(Arc<str>, OpId)>,
}
Expand description

The view as a dataflow.

Nodes are in dependency order — every input’s index is less than its consumer’s — so the engine is one forward pass with no scheduling.

Fields§

§nodes: Vec<Node>§constants: BTreeMap<OpId, Core>

Constants, in the same index space as nodes, for the ones whose op is Op::Const.

§root: OpId§state: OpId§session: OpId§presence: OpId§awareness: OpId§signals: Vec<(Arc<str>, OpId)>

The declared signals that survived as nodes, so a report can use the program’s own names.

Implementations§

Source§

impl Plan

Source

pub fn counts(&self) -> (usize, usize)

How many operators are maintained by delta, and how many are recomputed.

Sources and constants are neither: the accumulator, the session and a string literal are inputs to the dataflow rather than steps in it, and counting them as “recomputed” would make every program look worse than it is by a fixed amount.

Source

pub fn reapplied_per_event(&self) -> Vec<OpId> ⓘ

The operators whose per-element function captured something that moves on every event, so the whole collection is reapplied whenever anything happens.

This is the defect docs/99 §99.3 found by sweeping the tree by hand: a loop body that reads the accumulator is a different function after every event, so §23.13’s rebuild rule reapplies it to every element — a nested-loop join with no index, invisible until the collection is large. The operators of §99.9 remove it where the shape can be recognised, and §99.6’s rule for the shape that cannot is “compile it the slow way and say so”, which is Node::because.

Published so the sweep can be a standing property rather than a thing somebody re-runs. It was re-run by hand three times, and the third time found a site that had arrived one change after the second and been missed — the figure in the document was stale because the tree had grown under it (docs/08 §8.5.6’s third decay direction). incremental.rs::no_program_in_the_tree_reapplies_a_collection_per_event is what re-runs it now.

A per-subscription capture is not this and is not returned: a function that captured the session is reapplied when a subscriber navigates, which is a route change rather than an event, and calling the two the same thing is what made the hand sweep hard to read.

Source

pub fn shared(&self) -> Vec<OpId> ⓘ

The nodes that do not read the session: §5.3’s shared dataflow.

Source

pub fn compile(placed: &Placed) -> Plan

Compile the view of a sliced program, and fuse it.

Everything downstream — the engine, the read models, both reports — reads the fused plan, so there is one plan a program has rather than two that could disagree. Plan::unfused is what the differential gate compares against.

Source

pub fn compile_with(placed: &Placed, relate: Relate) -> Plan

The same, with Relate said out loud.

Source

pub fn of_query(tables: &[Arc<str>], body: &Core) -> Plan

A plan for one expression over collections the caller supplies — the read model’s SQL, compiled into the operators a program’s view compiles to (docs/99 §99.9 item 9).

tables names the fields of the record the engine is handed as its state: the ith of them holds the ith table’s rows, and the expression reads it as Var(i). That is the whole of the arrangement — a query has no session, no presence and no accumulator of its own, so the one source a view already has is the one a query uses too, and no operator here is new.

The expression is built rather than written, so it carries no CoreKind::Global and there is nothing for a definition table to answer; the decomposition is given an empty table. The consequence worth stating is that a query is held to exactly the recognitions a program is: crate::relate reads the loop and emits the Op::Join, the Op::ArrangeBy and the Op::GroupBy, so a join in SQL and a for loop that looks something up are the same operators with the same delta rules and not two implementations that agree.

Source

pub fn of_query_with(tables: &[Arc<str>], body: &Core, relate: Relate) -> Plan

The same, with Relate said out loud — which is what lets a gate measure both settings.

Source

pub fn unfused(placed: &Placed) -> Plan

The plan as the decomposition produced it, before crate::fuse rewrites it.

Works from the graph rather than from crate::split::Roles::view, for the reason docs/23 built the graph in the first place: the sliced expression has already lost which signal each part came from, and a plan whose nodes cannot be named is a plan no report can explain.

Source

pub fn unfused_with(placed: &Placed, relate: Relate) -> Plan

The same, with Relate said out loud.

Source

pub fn dependencies(&self, i: OpId) -> Vec<OpId> ⓘ

Every node an operator reads, including the ones its per-element function captured.

Source

pub fn names_of(&self, i: OpId) -> Vec<&str>

The names this plan gives one operator, if any — a declared signal is a name a developer wrote, and a report that can use it should.

Trait Implementations§

Source§

impl Clone for Plan

Source§

fn clone(&self) -> Plan

Returns a duplicate of the value. Read more
1.0.0 · Source§

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

Performs copy-assignment from source. Read more
Source§

impl Debug for Plan

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for Plan

§

impl RefUnwindSafe for Plan

§

impl Send for Plan

§

impl Sync for Plan

§

impl Unpin for Plan

§

impl UnwindSafe for Plan

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