Fast path for external importers (e.g. git-import) that already have pre-built `RecordedFile`s and just need globalization + assembly + hashing. Returns `(Change, Hash)`.
(
&self,
header: ChangeHeader,
recorded_files: &[atomic_core::record::workflow::RecordedFile],
)
| 1092 | /// |
| 1093 | /// Returns `(Change, Hash)`. |
| 1094 | pub fn assemble_and_hash( |
| 1095 | &self, |
| 1096 | header: ChangeHeader, |
| 1097 | recorded_files: &[atomic_core::record::workflow::RecordedFile], |
| 1098 | ) -> Result<(Change, Hash), RecordError> { |
| 1099 | use atomic_core::record::workflow::assemble_change; |
| 1100 | use atomic_core::record::workflow::assembly::AssemblyOptions; |
| 1101 | |
| 1102 | let overall_start = std::time::Instant::now(); |
| 1103 | |
| 1104 | let txn = self |
| 1105 | .pristine |
| 1106 | .read_txn() |
| 1107 | .map_err(|e| RecordError::Database(e.to_string()))?; |
| 1108 | |
| 1109 | // Use a bare transaction — no ViewGraph filter needed. |
| 1110 | // |
| 1111 | // This method is the fast path for git import, where every change |
| 1112 | // is written to a shared view and all edges land in the global |
| 1113 | // GRAPH table. A bare ReadTxn sees every edge directly. |
| 1114 | // |
| 1115 | // Wrapping in ViewGraph + collect_visible_change_ids would scan |
| 1116 | // the entire view change log on every call (O(N) per commit, |
| 1117 | // O(N²) total for N commits), which makes large imports |
| 1118 | // progressively slower. |
| 1119 | let assembly_options = AssemblyOptions::default(); |
| 1120 | |
| 1121 | let assembly_result = assemble_change(&txn, recorded_files, header, &assembly_options)?; |
| 1122 | |
| 1123 | let change = assembly_result.into_change(); |
| 1124 | log::debug!( |
| 1125 | "assemble_and_hash: assembly complete, content_size={} hunks={}", |
| 1126 | change.contents.len(), |
| 1127 | change.hunks().len(), |
| 1128 | ); |
| 1129 | |
| 1130 | let step = std::time::Instant::now(); |
| 1131 | let mut v3_bytes = Vec::new(); |
| 1132 | let hash = change |
| 1133 | .serialize(&mut v3_bytes) |
| 1134 | .map_err(|e| RecordError::ChangeStore(e.to_string()))?; |
| 1135 | let serialize_ms = step.elapsed().as_millis(); |
| 1136 | |
| 1137 | let step = std::time::Instant::now(); |
| 1138 | let (final_change, _) = Change::deserialize(&mut v3_bytes.as_slice()) |
| 1139 | .map_err(|e| RecordError::ChangeStore(e.to_string()))?; |
| 1140 | let deserialize_ms = step.elapsed().as_millis(); |
| 1141 | |
| 1142 | let total_ms = overall_start.elapsed().as_millis(); |
| 1143 | if serialize_ms + deserialize_ms > 100 { |
| 1144 | log::warn!( |
| 1145 | "assemble_and_hash: serialize={}ms ({} bytes) deserialize={}ms total={}ms", |
| 1146 | serialize_ms, |
| 1147 | v3_bytes.len(), |
| 1148 | deserialize_ms, |
| 1149 | total_ms, |
| 1150 | ); |
| 1151 | } else { |
nothing calls this directly
no test coverage detected