pub struct MemorySource {
pub schema: Schema,
/* private fields */
}Expand description
The in-memory source. fetch seeks a BTreeCursor
over a COW snapshot and drives it through source_common; write_change
path-copies via Rc::make_mut so in-flight cursors keep their snapshot (the
load-bearing COW property — §6).
Fields§
§schema: SchemaStatic table metadata (columns + PK). The per-connection sort lives on each
Connection; the schema’s own sort is reported to downstream operators
that need a child ordering (e.g. join relationship streams).
Implementations§
Source§impl MemorySource
impl MemorySource
Sourcepub fn validate_rows(schema: &Schema, rows: &[Row]) -> Result<(), RindleError>
pub fn validate_rows(schema: &Schema, rows: &[Row]) -> Result<(), RindleError>
Validate that every ingest row matches the schema’s column width (WS02.4): a
wrong-width row is rejected here with a RindleError::SchemaViolation rather
than reaching the engine’s unchecked column index (crate::value::RowRef::col)
where it would panic / abort.
Sourcepub fn try_new(
schema: Schema,
initial: Vec<Row>,
) -> Result<MemorySource, RindleError>
pub fn try_new( schema: Schema, initial: Vec<Row>, ) -> Result<MemorySource, RindleError>
Build a source over initial rows, validating each row’s width against
the schema first (WS02.4). The primary index is keyed by (pk asc); initial
is sorted under it and bulk-loaded (from_sorted, O(N)). Callers guarantee
initial has unique primary keys (a set). Prefer this over
MemorySource::new / crate::graph::Graph::add_source in production.
Sourcepub fn new(schema: Schema, initial: Vec<Row>) -> MemorySource
pub fn new(schema: Schema, initial: Vec<Row>) -> MemorySource
Panicking convenience wrapper over MemorySource::try_new (tests /
prototyping).
§Panics
If a row’s width does not match the schema. Prefer MemorySource::try_new
or crate::graph::Graph::try_add_source in production (WS02.6).
Sourcepub fn fork(&self) -> MemorySource
pub fn fork(&self) -> MemorySource
O(1) fork (memory-source.ts:135): a new source sharing the primary
index’s COW root (one Rc bump, no deep copy). Other indexes are NOT
carried (they rebuild lazily on demand, as in the JS).
Sourcepub fn fork_with_indexes(&self) -> MemorySource
pub fn fork_with_indexes(&self) -> MemorySource
Like fork, but COW-carries every index (each a one-Rc bump on its
B+tree root), not just the primary — the 203-MUTATOR-READS-DESIGN.md §7.3 (A) read-cache
optimization. A mutator’s one-shot tx.query that sorts in an order a live query already
built then shares that secondary index by COW lineage, collapsing its O(n log n) lazy
build to a bump. The carried indexes are kept current by
apply_change (it writes every index), so seeding the cache fork
(buffer replay) and write-forwarding maintain them. Used only for the off-graph
read-cache fork and its per-query fork-of-fork; the plain fork stays
primary-only for the optimistic sync baselines and the other COW snapshots that want the
lighter, divergence-bounded fork (OPTIMISTIC-WRITES-DESIGN.md §1.2).
Sourcepub fn get_index_keys(&self) -> Vec<Sort> ⓘ
pub fn get_index_keys(&self) -> Vec<Sort> ⓘ
Test hook: the set of index sorts currently held (indexes persist across
destroy — §3.10). Mirrors getIndexKeys (memory-source.ts:252).
Sourcepub fn fork_primary(&self) -> BTree
pub fn fork_primary(&self) -> BTree
An O(1) COW fork of the primary index tree (one Rc bump). The optimistic
loop’s sync/S' trees are forks of this — sharing the live tree’s node
lineage is what keeps structural_diff bounded by the divergence
(OPTIMISTIC-WRITES-DESIGN.md §1.2).
Sourcepub fn primary_sort(&self) -> &Sort
pub fn primary_sort(&self) -> &Sort
The primary-index sort ((pk[0] asc, pk[1] asc, …)) — the comparator every
fork/diff over fork_primary trees must use.
Sourcepub fn get_by_pk(&self, probe: &Row) -> Option<Row>
pub fn get_by_pk(&self, probe: &Row) -> Option<Row>
The current row whose primary key equals probe’s (other columns ignored by
the pk-only primary sort), or None. The optimistic MutationTx read path.
pub fn cursors_open(&self) -> i64
Sourcepub fn conn_count(&self) -> usize
pub fn conn_count(&self) -> usize
Total connection slots, including freed (recyclable) ones. Stays bounded by the peak live-connection count under query churn (the slot is recycled on teardown — it does NOT grow per teardown). For metrics/tests.
Sourcepub fn live_conn_count(&self) -> usize
pub fn live_conn_count(&self) -> usize
Number of live downstream connections (readers) — 0 once every pipeline reading this
source has been torn down. See ConnTable::live_conn_count.
Sourcepub fn set_conn_output(&self, conn: ConnId, edge: OutEdge)
pub fn set_conn_output(&self, conn: ConnId, edge: OutEdge)
Wire a connection’s downstream edge (mirrors input.setOutput).
Sourcepub fn push_candidates(&self, change: &SourceChange) -> Vec<u32>
pub fn push_candidates(&self, change: &SourceChange) -> Vec<u32>
The connection slots a write would fan out to — the push index’s candidate
set (designs/205). A test probe for the guarded / dynamic-guard pruning.
Sourcepub fn push_index_size(&self) -> usize
pub fn push_index_size(&self) -> usize
The push index’s entry count (see ConnTable::push_index_size) — a churn probe.
Sourcepub fn push(
&self,
change: SourceChange,
push_one: &dyn Fn(&Connection, SourceChange),
)
pub fn push( &self, change: SourceChange, push_one: &dyn Fn(&Connection, SourceChange), )
Eager push: fan change to every connection (overlay live, epoch-gated),
clear the overlay, then write to every index — via the backend-agnostic
source_common::gen_push_and_write_with_split_edit. push_one is the
graph’s downstream driver (it reads the connection’s output edge). Edit-
splitting, existence asserts, and the write-after-drain ordering all live
in source_common. push_one receives a SourceChange (rows); the graph
turns it into a node-bearing downstream Change at the connection boundary.
Sourcepub fn try_push(
&self,
change: SourceChange,
push_one: &dyn Fn(&Connection, SourceChange),
strict: bool,
) -> Result<(), RindleError>
pub fn try_push( &self, change: SourceChange, push_one: &dyn Fn(&Connection, SourceChange), strict: bool, ) -> Result<(), RindleError>
Fallible push used by strict change validation (WS02.2). Identical fan-out to
MemorySource::push but routed through the fallible source_common sibling
so a malformed change (when strict) returns a
RindleError::ConsistencyViolation. The memory exists/write are infallible,
so they wrap in Ok.
Sourcepub fn apply_change(&self, change: &SourceChange)
pub fn apply_change(&self, change: &SourceChange)
Apply ADD/REMOVE/EDIT to every index without the live push path’s existence
asserts and without the connection fan-out — for the off-graph read-cache
fork of 203-MUTATOR-READS-DESIGN.md (mutator reads). A read-cache fork has no
connections, so there is nothing to fan out to; this is purely the index write
that keeps the fork equal to live ⊕ this txn's buffer for its table (§4 / §4.1):
it seeds the fork (replay of the table’s buffered ops) and write-forwards each
later staged op. It is deliberately tolerant of the degenerate “edit a row that
isn’t there” case the staging path defers to commit (WriteTxn::edit), so a
later tx.query cannot panic on it.
Trait Implementations§
Source§impl ScalarSource for MemorySource
impl ScalarSource for MemorySource
Source§fn unique_keys(&self) -> Vec<Vec<ColId>>
fn unique_keys(&self) -> Vec<Vec<ColId>>
PK-only for the slice — the only statically-unique key a memory source has
(its other indexes are query-derived ordering structures, not uniqueness
constraints; SCALAR-SUBQUERY-DESIGN.md §4.3).
Source§fn lookup_unique(&self, bound: &[(ColId, OwnedValue)]) -> Option<Row>
fn lookup_unique(&self, bound: &[(ColId, OwnedValue)]) -> Option<Row>
(ColId, value) of bound holds. The caller
guarantees bound covers one of Self::unique_keys, so the result is
unique. None ⇒ no row matches (the empty-result fold).Source§impl Source for MemorySource
impl Source for MemorySource
Source§fn take_error(&self) -> Option<RindleError>
fn take_error(&self) -> Option<RindleError>
The in-memory backend is infallible — a fetch never parks an error.
Source§fn fetch<'g>(&'g self, conn: ConnId, req: &FetchRequest) -> RowFlow<'g>
fn fetch<'g>(&'g self, conn: ConnId, req: &FetchRequest) -> RowFlow<'g>
#fetch (the hot read path — memory-source.ts:257). Pick an index, seek
a scanStart RowBound, then drive the lending cursor through the
generator chain: overlay (index comparator) → start (connection comparator)
→ constraint (break) → filter. The two comparators differ by design when
a constraint is present (§3.1). Emits rows, not nodes — the connection
boundary (Graph::fetch on the SourceConn) wraps each row in a leaf node.
Source§fn connect(
&self,
sort: Option<Sort>,
filters: Option<ConnectionFilters>,
split_edit_keys: Vec<ColId>,
) -> ConnId
fn connect( &self, sort: Option<Sort>, filters: Option<ConnectionFilters>, split_edit_keys: Vec<ColId>, ) -> ConnId
sort = None ⇒
unordered. Self-joins call this twice. Builds the Connection from the
(07-compiled) filter spec + split-edit keys, and asserts the ordering
includes the PK when ordered. Mirrors connect (memory-source.ts:162).Source§fn conn_sort(&self, conn: ConnId) -> Sort
fn conn_sort(&self, conn: ConnId) -> Sort
Source§fn destroy(&self, conn: ConnId)
fn destroy(&self, conn: ConnId)
Source§fn cursors_open(&self) -> i64
fn cursors_open(&self) -> i64
0 ⇒ no cursor is mid-iteration and the connection is
free for a write.Source§fn try_push(
&self,
change: SourceChange,
push_one: &dyn Fn(&Connection, SourceChange),
strict: bool,
) -> Result<(), RindleError>
fn try_push( &self, change: SourceChange, push_one: &dyn Fn(&Connection, SourceChange), strict: bool, ) -> Result<(), RindleError>
change to every connection (overlay live,
epoch-gated), clear the overlay, then write. push_one is the graph’s
downstream driver. When strict, a malformed change returns a typed
RindleError instead of a debug_assert. (A backend may keep a faster
infallible push as an inherent method; this is the object-safe seam the
graph drives.)Source§fn set_conn_output(&self, conn: ConnId, edge: OutEdge)
fn set_conn_output(&self, conn: ConnId, edge: OutEdge)
input.setOutput).Source§fn add_guard_value(&self, conn: ConnId, value: OwnedValue)
fn add_guard_value(&self, conn: ConnId, value: OwnedValue)
conn (design 310 §4.1 — a family
root’s binding set growing; see ConnTable::add_guard_value). Required, not
defaulted: a decorator that forgot to forward it would leave the family root
unindexed and silently drop its deltas.Source§fn remove_guard_value(&self, conn: ConnId, value: &OwnedValue)
fn remove_guard_value(&self, conn: ConnId, value: &OwnedValue)
add_guard_value.