velesdb_core/lock_rank.rs
1//! Compiled lock-rank invariant for the global lock-acquisition order.
2//!
3//! Lock ordering was historically documented as convention in
4//! [`docs/CONCURRENCY_MODEL.md`]. This module promotes that convention to a
5//! typed [`LockRank`] newtype so the global acquisition order is expressed in
6//! code, with a debug-only [`assert_lock_order`] check that compiles to
7//! nothing in release builds (zero release overhead).
8//!
9//! Locks MUST be acquired in strictly ascending rank. Core ranks occupy the
10//! low ordinals (`gpu < vectors < columnar < layers < neighbors`); the
11//! inclusive range `[40, 59]` is reserved for premium-owned lock classes so
12//! premium can order its locks relative to core without collision.
13
14#[cfg(test)]
15#[path = "lock_rank_tests.rs"]
16mod lock_rank_tests;
17
18/// Ordinal encoding the global lock-acquisition order.
19///
20/// Locks MUST be acquired in strictly ascending rank; the debug-only
21/// [`assert_lock_order`] enforces this in debug builds. The type is a thin
22/// newtype over `u8` and derives a total ordering.
23#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
24pub struct LockRank(u8);
25
26impl LockRank {
27 /// GPU vector snapshot lock — lowest core rank.
28 pub const GPU_VECTORS_SNAPSHOT: LockRank = LockRank(5);
29 /// Dense-vector storage lock.
30 pub const VECTORS: LockRank = LockRank(10);
31 /// Columnar (`ColumnStore`) lock.
32 pub const COLUMNAR: LockRank = LockRank(15);
33 /// HNSW layer-structure lock.
34 pub const LAYERS: LockRank = LockRank(20);
35 /// HNSW neighbor-list lock — highest core rank.
36 pub const NEIGHBORS: LockRank = LockRank(30);
37
38 /// Inclusive lower bound of the reserved premium rank range.
39 ///
40 /// Core never assigns ranks at or above this value; premium declares
41 /// cluster-state / tenant-store / server-level ranks within `[40, 59]`
42 /// without colliding with core.
43 pub const PREMIUM_MIN: u8 = 40;
44 /// Inclusive upper bound of the reserved premium rank range.
45 pub const PREMIUM_MAX: u8 = 59;
46
47 /// Returns the underlying ordinal value.
48 #[must_use]
49 pub const fn ordinal(self) -> u8 {
50 self.0
51 }
52
53 /// Constructs a premium-owned rank, clamped to the reserved range.
54 ///
55 /// Returns `None` if `value` is outside the inclusive range
56 /// `[PREMIUM_MIN, PREMIUM_MAX]` (i.e. `[40, 59]`).
57 #[must_use]
58 pub const fn premium(value: u8) -> Option<LockRank> {
59 if value >= Self::PREMIUM_MIN && value <= Self::PREMIUM_MAX {
60 Some(LockRank(value))
61 } else {
62 None
63 }
64 }
65}
66
67/// Debug-only acquisition-order assertion.
68///
69/// Asserts that `about_to_acquire` has a strictly greater rank than
70/// `previously_held`. Compiles to nothing in release builds, so it carries
71/// zero release overhead.
72///
73/// # Panics
74/// In debug builds, panics if `about_to_acquire <= previously_held`, signaling
75/// a lock-order violation.
76#[inline]
77pub fn assert_lock_order(previously_held: LockRank, about_to_acquire: LockRank) {
78 debug_assert!(
79 about_to_acquire > previously_held,
80 "lock-order violation: acquiring rank {} while holding rank {}",
81 about_to_acquire.ordinal(),
82 previously_held.ordinal()
83 );
84}