Store content in the vault. Creates a `VaultEntry` from the given parameters, stores it in the database, and updates the manifest atomically. Returns the content hash (Blake3) of the stored entry. If an entry already exists at this path, it is replaced and the manifest is updated accordingly.
(
&self,
path: &str,
entry_type: VaultEntryType,
content: Vec<u8>,
frontmatter_json: String,
)
| 154 | /// If an entry already exists at this path, it is replaced and the |
| 155 | /// manifest is updated accordingly. |
| 156 | pub fn vault_store( |
| 157 | &self, |
| 158 | path: &str, |
| 159 | entry_type: VaultEntryType, |
| 160 | content: Vec<u8>, |
| 161 | frontmatter_json: String, |
| 162 | ) -> Result<Hash, RepositoryError> { |
| 163 | let now = chrono::Utc::now().to_rfc3339(); |
| 164 | let entry = VaultEntry::new(entry_type, content, frontmatter_json, now.clone()); |
| 165 | let content_hash = Hash::from_bytes(entry.content_hash); |
| 166 | |
| 167 | let mut txn = self |
| 168 | .pristine |
| 169 | .write_txn() |
| 170 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 171 | use atomic_core::pristine::{KgMutTxnT, VaultMutTxnT, VaultTxnT}; |
| 172 | |
| 173 | let previous_entry = txn |
| 174 | .get_vault_entry(path) |
| 175 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 176 | let cascade_updates = match previous_entry.as_ref() { |
| 177 | Some(previous) if previous.entry_type != entry_type => { |
| 178 | unlink_goal_from_intent_entries(&mut txn, path, previous, &now)? |
| 179 | } |
| 180 | _ => Vec::new(), |
| 181 | }; |
| 182 | if let Some(previous_entry_type) = previous_entry |
| 183 | .as_ref() |
| 184 | .map(|previous| previous.entry_type) |
| 185 | .filter(|previous| *previous != entry_type) |
| 186 | { |
| 187 | txn.init_kg() |
| 188 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 189 | txn.del_kg_node(&super::vault_triples::entry_subject( |
| 190 | path, |
| 191 | previous_entry_type, |
| 192 | )) |
| 193 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 194 | } |
| 195 | |
| 196 | txn.put_vault_entry(path, &entry) |
| 197 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 198 | |
| 199 | // Update manifest |
| 200 | let mut manifest = txn |
| 201 | .get_vault_manifest() |
| 202 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 203 | update_manifest_for_store(&mut manifest, path, &entry, previous_entry.as_ref(), &now); |
| 204 | apply_cascaded_intent_manifest_updates(&mut manifest, &cascade_updates, &now); |
| 205 | txn.put_vault_manifest(&manifest) |
| 206 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 207 | |
| 208 | txn.commit() |
| 209 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 210 | |
| 211 | self.vault_auto_index(path); |
| 212 | for update in cascade_updates { |
| 213 | self.vault_auto_index(&update.path); |