MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / build_dependent_tx_class

Function build_dependent_tx_class

nodedb/src/control/planner/calvin/dispatch.rs:238–287  ·  view source on GitHub ↗

Build a `TxClass` for a dependent-read (OLLP) transaction. For `BulkUpdate`/`BulkDelete` plans that have `ollp_predicted_surrogates` set, the OLLP collection's write set is built from `predicted_surrogates`. All other tasks in the batch are included using static surrogate extraction, exactly as `build_static_tx_class` does. This ensures multi-shard Calvin txns that contain an OLLP bulk operation

(
    tasks: &[PhysicalTask],
    tenant_id: TenantId,
    collection: &str,
    predicted_surrogates: &[u32],
)

Source from the content-addressed store, hash-verified

236///
237/// Returns `Err` if encoding fails or the resulting TxClass is invalid.
238pub fn build_dependent_tx_class(
239 tasks: &[PhysicalTask],
240 tenant_id: TenantId,
241 collection: &str,
242 predicted_surrogates: &[u32],
243) -> crate::Result<TxClass> {
244 use std::collections::BTreeMap;
245
246 // Accumulate per-collection surrogate sets. The OLLP collection uses the
247 // predicted surrogates; all other tasks use static key extraction.
248 let mut doc_surrogates: BTreeMap<String, Vec<u32>> = BTreeMap::new();
249
250 // Seed with the OLLP collection's predicted surrogates.
251 doc_surrogates
252 .entry(collection.to_owned())
253 .or_default()
254 .extend_from_slice(predicted_surrogates);
255
256 // Add static surrogates for all non-OLLP tasks.
257 for task in tasks {
258 let coll = collection_name_from_plan(&task.plan);
259 if coll.is_empty() || coll == collection {
260 continue;
261 }
262 let surrogate = surrogate_from_plan(&task.plan);
263 doc_surrogates.entry(coll).or_default().push(surrogate);
264 }
265
266 let mut write_sets: Vec<EngineKeySet> = doc_surrogates
267 .into_iter()
268 .map(|(coll, surrogates)| EngineKeySet::Document {
269 collection: coll,
270 surrogates: SortedVec::new(surrogates),
271 })
272 .collect();
273 write_sets.sort_by(|a, b| a.collection().cmp(b.collection()));
274
275 let write_set = ReadWriteSet::new(write_sets);
276 let read_set = ReadWriteSet::new(vec![]);
277
278 let plans: Vec<&PhysicalPlan> = tasks.iter().map(|t| &t.plan).collect();
279 let plans_bytes = zerompk::to_msgpack_vec(&plans).map_err(|e| Error::Serialization {
280 format: "msgpack".to_owned(),
281 detail: format!("failed to encode PhysicalPlan vec for Calvin dependent TxClass: {e}"),
282 })?;
283
284 TxClass::new(read_set, write_set, plans_bytes, tenant_id, None).map_err(|e| Error::BadRequest {
285 detail: format!("invalid dependent TxClass: {e}"),
286 })
287}
288
289/// Extract the collection name from a write plan.
290fn collection_name_from_plan(plan: &PhysicalPlan) -> String {

Callers 1

Calls 9

surrogate_from_planFunction · 0.85
entryMethod · 0.80
collectMethod · 0.80
is_emptyMethod · 0.45
pushMethod · 0.45
cmpMethod · 0.45
collectionMethod · 0.45
iterMethod · 0.45

Tested by

no test coverage detected