Skip to content

Commit 5d44064

Browse files
committed
refactor(engine): replace long argument lists with params structs
Convert the SQL plan visitor trait (scan, insert, upsert, update_from, join, and the vector/spatial/timeseries/array/lateral/hybrid-search variants), CRDT dead-letter/deferred/validator dispatch, cluster graph pattern matching, vector NaviX traversal, and WAL record/writer/replay paths to take dedicated params structs instead of long positional argument lists. Split the growing plan_visitor dispatch module into dispatch.rs/dispatch_rest.rs and factor the new arg structs into their own args.rs.
1 parent 5f95eb7 commit 5d44064

36 files changed

Lines changed: 1521 additions & 1126 deletions

File tree

nodedb-cluster/src/distributed_graph/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ pub mod wcc;
88

99
pub use coordinator::BspCoordinator;
1010
pub use pagerank::ShardPageRankState;
11-
pub use pattern_match::{DistributedMatchCoordinator, PatternContinuation, ShardMatchResult};
11+
pub use pattern_match::{
12+
DistributedMatchCoordinator, PatternContinuation, ResolvedContinuationArgs, ShardMatchResult,
13+
};
1214
pub use types::{AlgoComplete, BoundaryContributions, SuperstepAck, SuperstepBarrier};
1315
pub use wcc::stitch_components;

nodedb-cluster/src/distributed_graph/pattern_match.rs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,16 @@ pub struct DistributedMatchCoordinator {
7272
pub max_rounds: u32,
7373
}
7474

75+
/// Raw routing-resolved fields for [`PatternContinuation::from_resolved`].
76+
pub struct ResolvedContinuationArgs {
77+
pub target_shard: u32,
78+
pub source_shard: u32,
79+
pub bindings: HashMap<String, String>,
80+
pub next_triple_idx: usize,
81+
pub start_node: String,
82+
pub start_binding: String,
83+
}
84+
7585
impl PatternContinuation {
7686
/// Construct a continuation from its raw routing-resolved fields.
7787
///
@@ -81,15 +91,15 @@ impl PatternContinuation {
8191
/// routing classification itself stays in the CP layer — `nodedb-cluster`
8292
/// has no access to the routing table — but the field assembly lives with
8393
/// the type so the shape cannot drift from the struct definition.
84-
#[allow(clippy::too_many_arguments)]
85-
pub fn from_resolved(
86-
target_shard: u32,
87-
source_shard: u32,
88-
bindings: HashMap<String, String>,
89-
next_triple_idx: usize,
90-
start_node: String,
91-
start_binding: String,
92-
) -> Self {
94+
pub fn from_resolved(args: ResolvedContinuationArgs) -> Self {
95+
let ResolvedContinuationArgs {
96+
target_shard,
97+
source_shard,
98+
bindings,
99+
next_triple_idx,
100+
start_node,
101+
start_binding,
102+
} = args;
93103
Self {
94104
target_shard,
95105
source_shard,

nodedb-crdt/src/dead_letter.rs

Lines changed: 151 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,17 @@ pub struct DeadLetter {
105105
pub retry_count: u32,
106106
}
107107

108+
/// Parameters for [`DeadLetterQueue::enqueue`].
109+
pub struct EnqueueDeadLetterArgs<'a> {
110+
pub peer_id: u64,
111+
pub user_id: u64,
112+
pub tenant_id: u64,
113+
pub delta: Vec<u8>,
114+
pub constraint: &'a Constraint,
115+
pub reason: String,
116+
pub hint: CompensationHint,
117+
}
118+
108119
/// Bounded dead-letter queue.
109120
///
110121
/// Stores rejected deltas for later inspection and retry. The queue is bounded
@@ -126,17 +137,17 @@ impl DeadLetterQueue {
126137
}
127138

128139
/// Enqueue a rejected delta with full auth context.
129-
#[allow(clippy::too_many_arguments)]
130-
pub fn enqueue(
131-
&mut self,
132-
peer_id: u64,
133-
user_id: u64,
134-
tenant_id: u64,
135-
delta: Vec<u8>,
136-
constraint: &Constraint,
137-
reason: String,
138-
hint: CompensationHint,
139-
) -> Result<u64> {
140+
pub fn enqueue(&mut self, args: EnqueueDeadLetterArgs<'_>) -> Result<u64> {
141+
let EnqueueDeadLetterArgs {
142+
peer_id,
143+
user_id,
144+
tenant_id,
145+
delta,
146+
constraint,
147+
reason,
148+
hint,
149+
} = args;
150+
140151
if self.entries.len() >= self.capacity {
141152
return Err(CrdtError::DlqFull {
142153
capacity: self.capacity,
@@ -253,19 +264,19 @@ mod tests {
253264
let c = test_constraint();
254265

255266
let id = dlq
256-
.enqueue(
257-
42,
258-
0,
259-
0,
260-
b"delta-bytes".to_vec(),
261-
&c,
262-
"email already exists".into(),
263-
CompensationHint::RetryWithDifferentValue {
267+
.enqueue(EnqueueDeadLetterArgs {
268+
peer_id: 42,
269+
user_id: 0,
270+
tenant_id: 0,
271+
delta: b"delta-bytes".to_vec(),
272+
constraint: &c,
273+
reason: "email already exists".into(),
274+
hint: CompensationHint::RetryWithDifferentValue {
264275
field: "email".into(),
265276
conflicting_value: "alice@example.com".into(),
266277
suggestion: "alice+1@example.com".into(),
267278
},
268-
)
279+
})
269280
.unwrap();
270281

271282
assert_eq!(dlq.len(), 1);
@@ -285,12 +296,36 @@ mod tests {
285296
reason: "test".into(),
286297
};
287298

288-
dlq.enqueue(1, 0, 0, vec![], &c, "r1".into(), hint.clone())
289-
.unwrap();
290-
dlq.enqueue(2, 0, 0, vec![], &c, "r2".into(), hint.clone())
291-
.unwrap();
292-
293-
let err = dlq.enqueue(3, 0, 0, vec![], &c, "r3".into(), hint);
299+
dlq.enqueue(EnqueueDeadLetterArgs {
300+
peer_id: 1,
301+
user_id: 0,
302+
tenant_id: 0,
303+
delta: vec![],
304+
constraint: &c,
305+
reason: "r1".into(),
306+
hint: hint.clone(),
307+
})
308+
.unwrap();
309+
dlq.enqueue(EnqueueDeadLetterArgs {
310+
peer_id: 2,
311+
user_id: 0,
312+
tenant_id: 0,
313+
delta: vec![],
314+
constraint: &c,
315+
reason: "r2".into(),
316+
hint: hint.clone(),
317+
})
318+
.unwrap();
319+
320+
let err = dlq.enqueue(EnqueueDeadLetterArgs {
321+
peer_id: 3,
322+
user_id: 0,
323+
tenant_id: 0,
324+
delta: vec![],
325+
constraint: &c,
326+
reason: "r3".into(),
327+
hint,
328+
});
294329
assert!(matches!(err, Err(CrdtError::DlqFull { .. })));
295330
}
296331

@@ -314,14 +349,46 @@ mod tests {
314349
// Two entries for tenant 1 / users, one for tenant 1 / orders,
315350
// one for tenant 2 / users — only the first two should be
316351
// dropped by `purge_collection(1, "users")`.
317-
dlq.enqueue(10, 0, 1, vec![], &users_c, "a".into(), hint.clone())
318-
.unwrap();
319-
dlq.enqueue(11, 0, 1, vec![], &users_c, "b".into(), hint.clone())
320-
.unwrap();
321-
dlq.enqueue(12, 0, 1, vec![], &orders_c, "c".into(), hint.clone())
322-
.unwrap();
323-
dlq.enqueue(13, 0, 2, vec![], &users_c, "d".into(), hint.clone())
324-
.unwrap();
352+
dlq.enqueue(EnqueueDeadLetterArgs {
353+
peer_id: 10,
354+
user_id: 0,
355+
tenant_id: 1,
356+
delta: vec![],
357+
constraint: &users_c,
358+
reason: "a".into(),
359+
hint: hint.clone(),
360+
})
361+
.unwrap();
362+
dlq.enqueue(EnqueueDeadLetterArgs {
363+
peer_id: 11,
364+
user_id: 0,
365+
tenant_id: 1,
366+
delta: vec![],
367+
constraint: &users_c,
368+
reason: "b".into(),
369+
hint: hint.clone(),
370+
})
371+
.unwrap();
372+
dlq.enqueue(EnqueueDeadLetterArgs {
373+
peer_id: 12,
374+
user_id: 0,
375+
tenant_id: 1,
376+
delta: vec![],
377+
constraint: &orders_c,
378+
reason: "c".into(),
379+
hint: hint.clone(),
380+
})
381+
.unwrap();
382+
dlq.enqueue(EnqueueDeadLetterArgs {
383+
peer_id: 13,
384+
user_id: 0,
385+
tenant_id: 2,
386+
delta: vec![],
387+
constraint: &users_c,
388+
reason: "d".into(),
389+
hint: hint.clone(),
390+
})
391+
.unwrap();
325392

326393
let removed = dlq.purge_collection(1, "users");
327394
assert_eq!(removed, 2);
@@ -352,11 +419,36 @@ mod tests {
352419
reason: "test".into(),
353420
};
354421

355-
dlq.enqueue(1, 0, 0, vec![], &c, "a".into(), hint.clone())
356-
.unwrap();
357-
dlq.enqueue(2, 0, 0, vec![], &c, "b".into(), hint.clone())
358-
.unwrap();
359-
dlq.enqueue(1, 0, 0, vec![], &c, "c".into(), hint).unwrap();
422+
dlq.enqueue(EnqueueDeadLetterArgs {
423+
peer_id: 1,
424+
user_id: 0,
425+
tenant_id: 0,
426+
delta: vec![],
427+
constraint: &c,
428+
reason: "a".into(),
429+
hint: hint.clone(),
430+
})
431+
.unwrap();
432+
dlq.enqueue(EnqueueDeadLetterArgs {
433+
peer_id: 2,
434+
user_id: 0,
435+
tenant_id: 0,
436+
delta: vec![],
437+
constraint: &c,
438+
reason: "b".into(),
439+
hint: hint.clone(),
440+
})
441+
.unwrap();
442+
dlq.enqueue(EnqueueDeadLetterArgs {
443+
peer_id: 1,
444+
user_id: 0,
445+
tenant_id: 0,
446+
delta: vec![],
447+
constraint: &c,
448+
reason: "c".into(),
449+
hint,
450+
})
451+
.unwrap();
360452

361453
let peer1 = dlq.drain_peer(1);
362454
assert_eq!(peer1.len(), 2);
@@ -372,9 +464,27 @@ mod tests {
372464
};
373465

374466
let id1 = dlq
375-
.enqueue(1, 0, 0, vec![], &c, "a".into(), hint.clone())
467+
.enqueue(EnqueueDeadLetterArgs {
468+
peer_id: 1,
469+
user_id: 0,
470+
tenant_id: 0,
471+
delta: vec![],
472+
constraint: &c,
473+
reason: "a".into(),
474+
hint: hint.clone(),
475+
})
476+
.unwrap();
477+
let _id2 = dlq
478+
.enqueue(EnqueueDeadLetterArgs {
479+
peer_id: 1,
480+
user_id: 0,
481+
tenant_id: 0,
482+
delta: vec![],
483+
constraint: &c,
484+
reason: "b".into(),
485+
hint,
486+
})
376487
.unwrap();
377-
let _id2 = dlq.enqueue(1, 0, 0, vec![], &c, "b".into(), hint).unwrap();
378488

379489
let removed = dlq.remove(id1).unwrap();
380490
assert_eq!(removed.reason, "a");

0 commit comments

Comments
 (0)