Rewrite one session's derived index from its complete immutable turn set. This keeps local keys, manifest order, lifecycle pointers, and KG turn numbers consistent even when provenance arrives out of order.
(
&mut self,
mut record: crate::change::session::SessionRecord,
turns: Vec<crate::change::session::SessionTurn>,
)
| 447 | /// set. This keeps local keys, manifest order, lifecycle pointers, and KG |
| 448 | /// turn numbers consistent even when provenance arrives out of order. |
| 449 | fn rewrite_session_turns( |
| 450 | &mut self, |
| 451 | mut record: crate::change::session::SessionRecord, |
| 452 | turns: Vec<crate::change::session::SessionTurn>, |
| 453 | ) -> PristineResult<()> { |
| 454 | use crate::change::session::{ |
| 455 | canonicalize_session_turns, encode_session_turn_key, session_turn_namespace, |
| 456 | }; |
| 457 | |
| 458 | let old_turns = self.load_session_turns_for_write(&record.session_id)?; |
| 459 | let turns = canonicalize_session_turns(turns); |
| 460 | let preserved_edges = self.clear_session_turn_kg(&old_turns, &turns)?; |
| 461 | |
| 462 | let namespace = session_turn_namespace(&record.session_id); |
| 463 | let scan_start = encode_session_turn_key(namespace, 0); |
| 464 | let scan_end = encode_session_turn_key(namespace, u32::MAX); |
| 465 | let existing_keys = { |
| 466 | let table = self.txn.open_table(SESSION_TURNS)?; |
| 467 | let mut keys = Vec::new(); |
| 468 | for row in table.range::<&[u8; 40]>(&scan_start..=&scan_end)? { |
| 469 | let (key, _value) = row?; |
| 470 | keys.push(*key.value()); |
| 471 | } |
| 472 | keys |
| 473 | }; |
| 474 | { |
| 475 | let mut table = self.txn.open_table(SESSION_TURNS)?; |
| 476 | for key in existing_keys { |
| 477 | table.remove(&key)?; |
| 478 | } |
| 479 | } |
| 480 | { |
| 481 | let mut table = self.txn.open_table(SESSION_TURNS)?; |
| 482 | let mut reverse = self.txn.open_table(SESSION_PROVENANCE)?; |
| 483 | for turn in &turns { |
| 484 | let key = encode_session_turn_key(namespace, turn.turn_number); |
| 485 | let bytes = turn.to_bytes(); |
| 486 | table.insert(&key, bytes.as_slice())?; |
| 487 | reverse.insert(turn.provenance_hash.as_bytes(), &key)?; |
| 488 | } |
| 489 | } |
| 490 | |
| 491 | record.first_provenance = turns.first().map(|turn| turn.provenance_hash); |
| 492 | record.latest_provenance = turns.last().map(|turn| turn.provenance_hash); |
| 493 | record.turn_count = turns.len() as u32; |
| 494 | if let Some(first) = turns.first() { |
| 495 | record.started_at = record.started_at.min(first.timestamp); |
| 496 | } |
| 497 | { |
| 498 | let mut sessions = self.txn.open_table(SESSIONS)?; |
| 499 | let bytes = record.to_bytes(); |
| 500 | sessions.insert(record.session_id.as_str(), bytes.as_slice())?; |
| 501 | } |
| 502 | |
| 503 | let turn_numbers: std::collections::HashMap<Hash, u32> = turns |
| 504 | .iter() |
| 505 | .map(|turn| (turn.provenance_hash, turn.turn_number)) |
| 506 | .collect(); |
no test coverage detected