Skip to content

Commit 98ac1bd

Browse files
committed
refactor(lint): fix root causes instead of suppressing clippy lints
Replace needless range-loops with iterator adapters in the OPQ/RaBitQ quantizers and Vamana graph build, add OpLog::is_empty instead of allowing len_without_is_empty, drop a stale doc_markdown allow, and move the Send/Sync safety justification for the mmap-backed vector segment onto MmapVectorSegment itself so PlainMmapBacking no longer needs an arc_with_non_send_sync allow. Also split the over-long transaction batch commit and sub-plan dispatch functions into focused per-stage/per-engine helpers (sub_plan_write.rs), removing the too_many_lines allows.
1 parent 705dcd9 commit 98ac1bd

11 files changed

Lines changed: 639 additions & 323 deletions

File tree

nodedb-array/src/sync/op_log.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ pub type OpIter<'a> = Box<dyn Iterator<Item = ArrayResult<ArrayOp>> + 'a>;
2222
/// Implementations are expected to be `Send + Sync` and durable. An
2323
/// in-memory implementation suitable for tests is provided by
2424
/// [`InMemoryOpLog`] below.
25-
#[allow(clippy::len_without_is_empty)]
2625
pub trait OpLog: Send + Sync {
2726
/// Append an operation to the log.
2827
///
@@ -39,6 +38,11 @@ pub trait OpLog: Send + Sync {
3938
/// Return the total number of ops in the log (across all arrays).
4039
fn len(&self) -> ArrayResult<u64>;
4140

41+
/// Return `true` if the log contains no ops in any array.
42+
fn is_empty(&self) -> ArrayResult<bool> {
43+
Ok(self.len()? == 0)
44+
}
45+
4246
/// Drop all ops whose `hlc < hlc` and return the count dropped.
4347
///
4448
/// Used by GC after snapshotting ops below the min-ack frontier.

nodedb-codec/src/vector_quant/opq.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,11 +209,10 @@ fn matvec(r: &[f32], v: &[f32], dim: usize) -> Vec<f32> {
209209

210210
fn pq_encode(v: &[f32], codebooks: &[Vec<Vec<f32>>], m: usize, sub_dim: usize) -> Vec<u8> {
211211
let mut codes = Vec::with_capacity(m);
212-
#[allow(clippy::needless_range_loop)]
213-
for s in 0..m {
212+
for (s, codebook) in codebooks.iter().enumerate().take(m) {
214213
let offset = s * sub_dim;
215214
let sub = &v[offset..offset + sub_dim];
216-
let best = codebooks[s]
215+
let best = codebook
217216
.iter()
218217
.enumerate()
219218
.min_by(|(_, a), (_, b)| {

nodedb-codec/src/vector_quant/rabitq.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,14 +245,13 @@ impl RaBitQCodec {
245245
wht_inplace(&mut sign_buf);
246246
// Re-apply signed diagonal (D is its own inverse since flips are ±1)
247247
let mut seed = self.rotation_seed;
248-
#[allow(clippy::needless_range_loop)]
249-
for i in 0..dim {
248+
for x in sign_buf.iter_mut().take(dim) {
250249
let flip = if xorshift64(&mut seed) & 1 == 0 {
251250
1.0f32
252251
} else {
253252
-1.0f32
254253
};
255-
sign_buf[i] *= flip;
254+
*x *= flip;
256255
}
257256
let dot_raw: f32 = residual
258257
.iter()

nodedb-physical/src/physical_plan/document/op.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ pub enum DocumentOp {
7070
/// If non-empty, the Data Plane evaluates these after fetching
7171
/// the document. Returns `NOT_FOUND` on denial (no info leak).
7272
/// Injected by the Control Plane planner from RLS policies.
73-
#[allow(clippy::doc_markdown)]
7473
rls_filters: Vec<u8>,
7574
/// System-time selection. `Current` = current state. Honored only by
7675
/// bitemporal collections; the planner rejects temporal point-gets on

nodedb-vector/src/mmap_segment/reader.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ use crate::error::VectorError;
2121
/// Exposes a `&[f32]` view of the vector data block and a `&[u64]` view of
2222
/// the surrogate ID block — both zero-copy slices into the mmap region.
2323
///
24-
/// Not `Send` or `Sync` — owned by a single Data Plane core.
24+
/// Typically owned by a single Data Plane core, but safe to share across
25+
/// threads behind an [`Arc`]: see the `Send`/`Sync` safety note below.
2526
#[derive(Debug)]
2627
pub struct MmapVectorSegment {
2728
path: PathBuf,
@@ -41,6 +42,13 @@ pub struct MmapVectorSegment {
4142
_budget_guard: Option<BudgetGuard>,
4243
}
4344

45+
// SAFETY: `MmapVectorSegment` holds a `*const u8` (`base`) into a read-only
46+
// `MAP_PRIVATE` mmap region. The region is immutable after construction,
47+
// process-global, and valid for the lifetime of the value. There is no
48+
// interior mutability, so concurrent reads from multiple threads are sound.
49+
unsafe impl Send for MmapVectorSegment {}
50+
unsafe impl Sync for MmapVectorSegment {}
51+
4452
impl MmapVectorSegment {
4553
// ── Constructors ──────────────────────────────────────────────────────────
4654

nodedb-vector/src/segment_backing/plain.rs

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,28 +36,15 @@ use super::VectorSegmentBacking;
3636
/// The `Arc<MmapVectorSegment>` wrapper ensures the segment (and therefore
3737
/// the mmap region) outlives any `&[f32]` slice handed out through this type.
3838
///
39-
/// SAFETY: given the above invariants, treating `PlainMmapBacking` as
40-
/// `Send + Sync` is correct.
39+
/// `PlainMmapBacking` is `Send + Sync` automatically: [`MmapVectorSegment`]
40+
/// carries the `unsafe impl Send + Sync` (justified by the invariants above),
41+
/// so `Arc<MmapVectorSegment>` — and therefore this wrapper — is too.
4142
pub struct PlainMmapBacking {
4243
inner: Arc<MmapVectorSegment>,
4344
}
4445

45-
// SAFETY: see struct-level doc comment. `MmapVectorSegment` holds a
46-
// `*const u8` (`base`) into a read-only MAP_PRIVATE mmap region. The region
47-
// is immutable after construction, process-global, and valid for the lifetime
48-
// of the Arc. No interior mutability exists; concurrent reads are safe.
49-
unsafe impl Send for PlainMmapBacking {}
50-
unsafe impl Sync for PlainMmapBacking {}
51-
5246
impl PlainMmapBacking {
5347
/// Wrap a [`MmapVectorSegment`] that is not yet reference-counted.
54-
///
55-
/// `MmapVectorSegment` holds a `*const u8` raw pointer which makes it
56-
/// `!Send + !Sync` by default. The `unsafe impl Send + Sync` on
57-
/// `PlainMmapBacking` (see struct-level doc comment) establishes the safety
58-
/// invariants; clippy cannot see through the `Arc` to the impl, so we
59-
/// suppress the lint here.
60-
#[allow(clippy::arc_with_non_send_sync)]
6148
pub fn new(seg: MmapVectorSegment) -> Self {
6249
Self {
6350
inner: Arc::new(seg),

nodedb-vector/src/vamana/build.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,8 @@ pub fn build_vamana<C: VectorCodec>(
9393
}
9494

9595
// --- Pass 1 refinement: beam-search to replace random neighbors ---
96-
#[allow(clippy::needless_range_loop)]
97-
for i in 0..n {
98-
let query = codec.prepare_query(&vectors[i]);
96+
for (i, vector) in vectors.iter().enumerate().take(n) {
97+
let query = codec.prepare_query(vector);
9998
let candidates = greedy_beam_search_quantized(&graph, &query, codec, quantized, i, l);
10099
// Take the R closest from the candidates, excluding self.
101100
let mut nbrs: Vec<(u32, f32)> = candidates

nodedb/src/data/executor/handlers/transaction/batch.rs

Lines changed: 107 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ use nodedb_physical::physical_plan::PhysicalPlan;
1818

1919
use super::undo::UndoEntry;
2020

21+
/// A CRDT delta buffered during a transaction batch: `(delta_bytes, id,
22+
/// collection)`. Deltas accumulate in a scratch buffer and are applied to
23+
/// the LoroDoc only on full-batch success.
24+
type CrdtDelta = (Vec<u8>, u64, String);
25+
2126
impl CoreLoop {
2227
/// Execute a transaction batch atomically.
2328
///
@@ -27,7 +32,6 @@ impl CoreLoop {
2732
///
2833
/// The Control Plane has already written a single `RecordType::Transaction`
2934
/// WAL record covering all operations before dispatching this batch.
30-
#[allow(clippy::too_many_lines)]
3135
pub(in crate::data::executor) fn execute_transaction_batch(
3236
&mut self,
3337
task: &ExecutionTask,
@@ -40,16 +44,68 @@ impl CoreLoop {
4044
"transaction batch begin"
4145
);
4246

43-
let mut undo_log: Vec<UndoEntry> = Vec::with_capacity(plans.len());
44-
let mut crdt_deltas: Vec<(Vec<u8>, u64, String)> = Vec::new();
47+
let undo_log: Vec<UndoEntry> = Vec::with_capacity(plans.len());
48+
let crdt_deltas: Vec<CrdtDelta> = Vec::new();
49+
50+
let (last_response, undo_log, crdt_deltas) =
51+
match self.run_sub_plans(task, tid, plans, undo_log, crdt_deltas) {
52+
Ok(v) => v,
53+
Err(resp) => return resp,
54+
};
55+
56+
let undo_log = match self.apply_balanced_constraint_check(task, tid, undo_log) {
57+
Ok(u) => u,
58+
Err(resp) => return resp,
59+
};
60+
61+
if let Some(resp) = self.apply_crdt_deltas(task, tid, crdt_deltas) {
62+
return resp;
63+
}
64+
65+
debug!(
66+
core = self.core_id,
67+
committed = plans.len(),
68+
"transaction batch committed"
69+
);
70+
71+
self.emit_deferred_writes(task, undo_log);
72+
73+
// Return the last sub-plan payload, but keyed to the outer transaction request.
74+
Response {
75+
request_id: task.request_id(),
76+
status: Status::Ok,
77+
attempt: 1,
78+
partial: false,
79+
payload: last_response.payload,
80+
watermark_lsn: self.watermark,
81+
error_code: None,
82+
}
83+
}
84+
85+
/// Run every sub-plan in order, tracking undo entries and buffered CRDT
86+
/// deltas as it goes.
87+
///
88+
/// On success, returns the last sub-plan's response plus the accumulated
89+
/// undo log and CRDT delta buffer (for the caller's subsequent commit
90+
/// steps). On failure, rolls back all writes performed so far and
91+
/// returns the terminal error `Response` directly — the caller must
92+
/// return it unchanged.
93+
///
94+
/// A panic (real or test-injected) during a sub-apply is caught so it
95+
/// routes through the same typed-rollback path instead of unwinding past
96+
/// `undo_log`, which would drop the log without running rollback and
97+
/// leave the shard half-committed.
98+
fn run_sub_plans(
99+
&mut self,
100+
task: &ExecutionTask,
101+
tid: u64,
102+
plans: &[PhysicalPlan],
103+
mut undo_log: Vec<UndoEntry>,
104+
mut crdt_deltas: Vec<CrdtDelta>,
105+
) -> Result<(Response, Vec<UndoEntry>, Vec<CrdtDelta>), Response> {
45106
let mut last_response = self.response_ok(task);
46107

47108
for (i, plan) in plans.iter().enumerate() {
48-
// Wrap the sub-apply + post-apply fail-point in catch_unwind so a
49-
// panic (real or test-injected) routes through the typed-rollback
50-
// arm below instead of unwinding past `undo_log`. Without this,
51-
// a panic between sub-applies would drop the undo log without
52-
// running rollback and leave the shard half-committed.
53109
let user_roles = &task.request.user_roles;
54110
let outcome = catch_unwind(AssertUnwindSafe(|| {
55111
let r = self.execute_tx_sub_plan(
@@ -118,20 +174,32 @@ impl CoreLoop {
118174
// Discard CRDT scratch buffer (never applied).
119175
drop(crdt_deltas);
120176

121-
return Response {
177+
return Err(Response {
122178
request_id: task.request_id(),
123179
status: Status::Error,
124180
attempt: 1,
125181
partial: false,
126182
payload: crate::bridge::envelope::Payload::empty(),
127183
watermark_lsn: self.watermark,
128184
error_code: Some(rollback_error_code),
129-
};
185+
});
130186
}
131187
}
132188
}
133189

134-
// Pre-commit: BALANCED constraint check across all inserts in this transaction.
190+
Ok((last_response, undo_log, crdt_deltas))
191+
}
192+
193+
/// Pre-commit: check the `BALANCED` constraint across all inserts in
194+
/// this transaction. On violation, rolls back and returns the terminal
195+
/// error `Response`; on success, hands the undo log back for the
196+
/// deferred-trigger step.
197+
fn apply_balanced_constraint_check(
198+
&mut self,
199+
task: &ExecutionTask,
200+
tid: u64,
201+
undo_log: Vec<UndoEntry>,
202+
) -> Result<Vec<UndoEntry>, Response> {
135203
if let Err(error_code) =
136204
self.check_balanced_constraints(task.request.database_id.as_u64(), tid, &undo_log)
137205
{
@@ -160,24 +228,35 @@ impl CoreLoop {
160228
}
161229
}
162230
};
163-
return Response {
231+
return Err(Response {
164232
request_id: task.request_id(),
165233
status: Status::Error,
166234
attempt: 1,
167235
partial: false,
168236
payload: crate::bridge::envelope::Payload::empty(),
169237
watermark_lsn: self.watermark,
170238
error_code: Some(rollback_error_code),
171-
};
239+
});
172240
}
241+
Ok(undo_log)
242+
}
173243

174-
// All sub-plans succeeded. Apply buffered CRDT deltas.
175-
// Failure here means the CRDT state is inconsistent with the already-committed
176-
// forward writes — return RollbackFailed so the client knows the shard needs
177-
// a restart to restore consistency via WAL replay. Never warn-and-continue.
244+
/// Apply all buffered CRDT deltas now that every sub-plan and the
245+
/// `BALANCED` constraint check have succeeded.
246+
///
247+
/// Failure here means the CRDT state is inconsistent with the
248+
/// already-committed forward writes — returns a `RollbackFailed`
249+
/// `Response` so the client knows the shard needs a restart to restore
250+
/// consistency via WAL replay. Never warn-and-continue.
251+
fn apply_crdt_deltas(
252+
&mut self,
253+
task: &ExecutionTask,
254+
tid: u64,
255+
crdt_deltas: Vec<CrdtDelta>,
256+
) -> Option<Response> {
178257
for (crdt_idx, (delta, _peer_id, collection)) in crdt_deltas.into_iter().enumerate() {
179-
// Second crash-injection point — between forward-write commit and
180-
// CRDT apply. WAL replay must roll the CRDT side forward (or roll
258+
// Crash-injection point — between forward-write commit and CRDT
259+
// apply. WAL replay must roll the CRDT side forward (or roll
181260
// forward writes back) to restore consistency.
182261
crate::fail_point!("transaction_batch::between_crdt_delta");
183262

@@ -197,7 +276,7 @@ impl CoreLoop {
197276
"CRDT delta apply failed after forward writes committed; \
198277
shard state unknown — restart required for WAL replay"
199278
);
200-
return Response {
279+
return Some(Response {
201280
request_id: task.request_id(),
202281
status: Status::Error,
203282
attempt: 1,
@@ -208,7 +287,7 @@ impl CoreLoop {
208287
entry_index: crdt_idx,
209288
detail: format!("CRDT delta apply failed: {e}"),
210289
}),
211-
};
290+
});
212291
}
213292
}
214293
Err(e) => {
@@ -219,7 +298,7 @@ impl CoreLoop {
219298
"CRDT engine not found after forward writes committed; \
220299
shard state unknown — restart required for WAL replay"
221300
);
222-
return Response {
301+
return Some(Response {
223302
request_id: task.request_id(),
224303
status: Status::Error,
225304
attempt: 1,
@@ -230,18 +309,16 @@ impl CoreLoop {
230309
entry_index: crdt_idx,
231310
detail: format!("CRDT engine not available: {e}"),
232311
}),
233-
};
312+
});
234313
}
235314
}
236315
}
316+
None
317+
}
237318

238-
debug!(
239-
core = self.core_id,
240-
committed = plans.len(),
241-
"transaction batch committed"
242-
);
243-
244-
// Emit deferred trigger events for all writes in the committed transaction.
319+
/// Emit deferred trigger events for every write recorded in the
320+
/// committed transaction's undo log.
321+
fn emit_deferred_writes(&mut self, task: &ExecutionTask, undo_log: Vec<UndoEntry>) {
245322
use crate::data::executor::core_loop::deferred::DeferredWrite;
246323
let deferred_writes: Vec<DeferredWrite> = undo_log
247324
.into_iter()
@@ -286,17 +363,6 @@ impl CoreLoop {
286363
task.request.vshard_id,
287364
);
288365
}
289-
290-
// Return the last sub-plan payload, but keyed to the outer transaction request.
291-
Response {
292-
request_id: task.request_id(),
293-
status: Status::Ok,
294-
attempt: 1,
295-
partial: false,
296-
payload: last_response.payload,
297-
watermark_lsn: self.watermark,
298-
error_code: None,
299-
}
300366
}
301367
}
302368

nodedb/src/data/executor/handlers/transaction/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ mod sub_plan;
77
mod sub_plan_doc;
88
mod sub_plan_kv;
99
mod sub_plan_kv_ops;
10+
mod sub_plan_write;
1011
pub(super) mod undo;

0 commit comments

Comments
 (0)