Skip to main content

codetether_agent/rlm/oracle/storage/manager/
persist.rs

1//! Public persist methods for [`OracleTraceStorage`].
2//!
3//! Handles spool writes and delegates upload attempts to
4//! internal helpers in [`super::internals`].
5//!
6//! # Examples
7//!
8//! ```ignore
9//! let out = storage.persist_record(&record).await?;
10//! assert!(!out.spooled_path.is_empty());
11//! ```
12
13use super::super::spool_io::{spool_filename, write_json_atomic};
14use super::super::types::OracleTracePersistResult;
15use super::OracleTraceStorage;
16use crate::rlm::oracle::record::OracleTraceRecord;
17use crate::rlm::oracle::trace_types::OracleResult;
18use anyhow::{Context, Result};
19use chrono::Utc;
20
21impl OracleTraceStorage {
22    /// Convert an [`OracleResult`] to a record and persist it.
23    ///
24    /// # Examples
25    ///
26    /// ```ignore
27    /// let out = storage.persist_result(&oracle_result).await?;
28    /// ```
29    pub async fn persist_result(&self, result: &OracleResult) -> Result<OracleTracePersistResult> {
30        self.persist_record(&result.to_record()).await
31    }
32
33    /// Write `record` to local spool and attempt remote upload.
34    ///
35    /// # Examples
36    ///
37    /// ```ignore
38    /// let out = storage.persist_record(&record).await?;
39    /// ```
40    pub async fn persist_record(
41        &self,
42        record: &OracleTraceRecord,
43    ) -> Result<OracleTracePersistResult> {
44        tokio::fs::create_dir_all(&self.spool_dir)
45            .await
46            .with_context(|| format!("Create spool dir {}", self.spool_dir.display()))?;
47        self.warn_if_spool_large().await;
48
49        let path = self
50            .spool_dir
51            .join(spool_filename(record, Utc::now().timestamp_millis()));
52        write_json_atomic(&path, record).await?;
53
54        let (uploaded, remote_key, remote_url, warning) = self.try_upload(record, &path).await;
55        let pending_count = self.pending_count().await?;
56        Ok(OracleTracePersistResult {
57            verdict: record.verdict.clone(),
58            spooled_path: path.display().to_string(),
59            uploaded,
60            remote_key,
61            remote_url,
62            pending_count,
63            warning,
64        })
65    }
66}