omnigraph/db/mod.rs
1pub mod commit_graph;
2pub mod graph_coordinator;
3pub mod manifest;
4mod omnigraph;
5mod recovery_audit;
6mod schema_state;
7pub(crate) mod write_queue;
8
9pub use commit_graph::GraphCommit;
10pub use graph_coordinator::{GraphCoordinator, ReadTarget, ResolvedTarget, SnapshotId};
11pub use manifest::{Snapshot, SubTableEntry, SubTableUpdate};
12pub(crate) use omnigraph::ensure_public_branch_ref;
13pub use omnigraph::{
14 CleanupPolicyOptions, InitOptions, MergeOutcome, Omnigraph, OpenMode, RepairAction,
15 RepairClassification, RepairOptions, RepairStats, SchemaApplyOptions, SchemaApplyResult,
16 SkipReason, TableCleanupStats, TableOptimizeStats, TableRepairStats,
17};
18
19pub(crate) const SCHEMA_APPLY_LOCK_BRANCH: &str = "__schema_apply_lock__";
20
21/// Mutation kind, threaded through the version-check call sites so the
22/// engine can apply an op-kind-aware policy:
23///
24/// - `Insert` / `Merge`: skip the strict pre-stage `ensure_expected_version`
25/// check. Lance's `MergeInsertBuilder` rebases concurrent appends; the
26/// per-(table, branch) writer queue serializes `commit_staged`; the
27/// publisher's CAS (refreshed under the queue via
28/// `MutationStaging::commit_all`'s `snapshot_for_branch` call) catches
29/// genuine cross-process drift as `ManifestConflictDetails::ExpectedVersionMismatch`.
30/// The pre-stage strict check would over-reject in-process concurrent
31/// inserts, which is exactly the case PR 2 / MR-686 designed the
32/// per-table queue to allow.
33///
34/// - `Update` / `Delete`: keep the strict check. These have read-modify-write
35/// semantics; Lance moving between the read at stage time and the write
36/// at commit time means the staged batch is computed against stale state.
37/// The strict check guards the per-query SI invariant. SERIALIZABLE
38/// opt-in (§VI.36 future seam) is the long-term answer for tighter
39/// semantics; today, in-process update-update races on the same key
40/// stay rejected as 409 — acceptable.
41///
42/// - `SchemaRewrite`: keep the strict check. Schema apply runs under the
43/// graph-wide `__schema_apply_lock__` AND per-table queues; the strict
44/// check is uncontested at that point.
45#[derive(Debug, Clone, Copy, PartialEq, Eq)]
46pub(crate) enum MutationOpKind {
47 Insert,
48 Merge,
49 Update,
50 Delete,
51 SchemaRewrite,
52}
53
54impl MutationOpKind {
55 /// Whether the strict pre-stage `ensure_expected_version` check should
56 /// fire for this op kind. See [`MutationOpKind`] for the rationale per
57 /// kind.
58 pub(crate) fn strict_pre_stage_version_check(self) -> bool {
59 match self {
60 MutationOpKind::Insert | MutationOpKind::Merge => false,
61 MutationOpKind::Update | MutationOpKind::Delete | MutationOpKind::SchemaRewrite => true,
62 }
63 }
64}
65
66pub(crate) fn is_schema_apply_lock_branch(name: &str) -> bool {
67 name.trim_start_matches('/') == SCHEMA_APPLY_LOCK_BRANCH
68}
69
70pub(crate) fn is_internal_system_branch(name: &str) -> bool {
71 // Legacy `__run__*` staging branches (Run state machine, removed MR-771)
72 // are swept off `__manifest` by the v2→v3 internal-schema migration, so the
73 // only internal branch the engine still creates is the schema-apply lock.
74 is_schema_apply_lock_branch(name)
75}