Omnigraph Atlas Omnigraph's documentation, bound to its Rust workspace
79 documents

How a write becomes durable

Follow a mutation from the query executor through in-memory staging, the single manifest-publish CAS fence, and crash recovery — the heart of Omnigraph's atomicity guarantee.

Mutation execution (exec/mutation.rs)

Resolves expression values to literals, converts to typed Arrow arrays (literal_to_typed_array(lit, DataType, num_rows)), then writes via Lance's two-phase distributed-write API at end-of-query:

  • insert (no @key, edges) → accumulate into MutationStaging.pending (Append mode); finalize calls stage_append once per touched table.
  • insert (@key node) → accumulate into pending (Merge mode); finalize calls stage_merge_insert once per touched table.
  • update → scan committed via Lance + pending via DataFusion MemTable (read-your-writes), apply assignments, accumulate into pending (Merge mode).
  • delete → still inline-commits via delete_where (Lance v6.0.1 has no public two-phase delete; DeleteBuilder::execute_uncommitted first ships in v7.0.0-beta.10 — tracked as MR-A in docs/dev/lance.md); recorded into MutationStaging.inline_committed.

D₂ parse-time rule. A single mutation query is either insert/update-only or delete-only. Mixed → reject before any I/O. The check fires in enforce_no_mixed_destructive_constructive(&ir) inside execute_named_mutation.

Multi-statement mutations are atomic at the publisher commit boundary: every insert/update batch lives in memory until end-of-query, then exactly one stage_* + commit_staged runs per touched table, then ManifestBatchPublisher::publish commits the manifest atomically with per-table expected_table_versions CAS.