WeaveDocs
Nexus

Strand Inputs

Strand inputs in Nexus — register input strands, track per-strand stats, and feed projections deterministically.

Purpose

Multi-strand ordered views with governance, custom ordering, strand input stats, and materialized projections.

This page follows the real source shape for Nexus and explains the workflow a developer is likely to use first.

Developer workflow

Start from the smallest constructor or builder, perform one meaningful operation, inspect the returned state, then add the relevant policy, storage, or network integration. The examples below should be expanded whenever the crate API changes.

Tip

Register inputs eagerly. A view's output is consistent only across the strands it knows about — adding a strand later means re-materialising from scratch (or accepting a discontinuity in output ordering).

Primary types to know

  • AllowAllPolicy — models/nexus/src/governance.rs
  • ApprovalRecord — models/nexus/src/governance.rs
  • CustomOrdering — models/nexus/src/ordering.rs
  • GovernancePolicy — models/nexus/src/governance.rs
  • GovernanceRules — models/nexus/src/governance.rs
  • IndexOrdering — models/nexus/src/ordering.rs
  • InputStrand — models/nexus/src/strand_input.rs
  • MemoryView — models/nexus/src/view.rs
  • Nexus — models/nexus/src/nexus.rs
  • NexusConfig — models/nexus/src/config.rs
  • NexusCursor — models/nexus/src/view.rs
  • Page — models/nexus/src/view.rs

Example shape

use nexus::{InputStrand, StrandStats};
use std::sync::Arc;
use strand::{Strand, StrandConfig};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Build an upstream writer Strand and append three events.
    let dir = tempfile::tempdir()?;
    let mut writer = Strand::new(StrandConfig::new().with_storage(dir.path())).await?;
    for payload in [b"e1".as_slice(), b"e2", b"e3"] {
        writer.append(payload).await?;
    }

    // Wrap it as a Nexus InputStrand. The Nexus tracks how far it has consumed
    // via an atomic processed_length so multi-strand merging is incremental.
    let input = InputStrand::new(Arc::new(writer));
    assert_eq!(input.processed_length(), 0);
    assert!(input.has_new_entries().await?);

    // Simulate the Nexus reader advancing across the first two events.
    input.set_processed_length(2);

    let stats = StrandStats::from_input_strand(&input).await?;
    println!(
        "writer_key_prefix={} total={} processed={} unprocessed={}",
        &stats.writer_key[..16.min(stats.writer_key.len())],
        stats.total_entries,
        stats.processed_entries,
        stats.unprocessed_entries,
    );
    Ok(())
}