gioser
⎇ d6b8f18b43c9bd9bf7268e48b61392a2d62bb229 crates/ente-snapshot/src/lib.rs Rust · 61 líneas · 2.0 KB Historia Quién tocó qué crudo

Pausa: 11 crates del fractal Ente #0 con cerebro completo d6b8f18b4 · Sergio ·

1//! Persistencia del fractal. Captura el estado live (Cards encarnadas con
2//! sus identidades preservadas) a un blob JSON. Al restaurar, las mismas
3//! Ulids vuelven a la vida — los PIDs cambian (kernel no los preserva) pero
4//! el grafo se reconstruye con la misma topología.
5//!
6//! Lo que NO se persiste:
7//!   - PIDs (irrelevantes tras reboot)
8//!   - bus_connections (runtime-only)
9//!   - pending_invokes (en vuelo, se descartan)
10//!   - device presence (uevents reconstruyen el índice)
11
12use ente_card::EntityCard;
13use serde::{Deserialize, Serialize};
14use std::path::Path;
15use ulid::Ulid;
16
17pub const SNAPSHOT_VERSION: u16 = 1;
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct FractalSnapshot {
21    pub version: u16,
22    pub timestamp_ms: u64,
23    pub seed_id: Ulid,
24    pub seed_label: String,
25    /// Cards live al momento del checkpoint, excluyendo la Semilla.
26    /// Al restaurar se inyectan en `genesis` con sus Ulids originales.
27    pub entes: Vec<EntityCard>,
28}
29
30impl FractalSnapshot {
31    pub fn write(&self, path: &Path) -> anyhow::Result<()> {
32        let bytes = serde_json::to_vec_pretty(self)?;
33        if let Some(parent) = path.parent() {
34            std::fs::create_dir_all(parent).ok();
35        }
36        // Escritura atómica: temp file + rename.
37        let tmp = path.with_extension("tmp");
38        std::fs::write(&tmp, &bytes)?;
39        std::fs::rename(&tmp, path)?;
40        Ok(())
41    }
42
43    pub fn read(path: &Path) -> anyhow::Result<Self> {
44        let bytes = std::fs::read(path)?;
45        let snap: FractalSnapshot = serde_json::from_slice(&bytes)?;
46        if snap.version != SNAPSHOT_VERSION {
47            anyhow::bail!(
48                "snapshot version {} no soportada (esperada {})",
49                snap.version, SNAPSHOT_VERSION
50            );
51        }
52        Ok(snap)
53    }
54}
55
56pub fn now_ms() -> u64 {
57    std::time::SystemTime::now()
58        .duration_since(std::time::UNIX_EPOCH)
59        .map(|d| d.as_millis() as u64)
60        .unwrap_or(0)
61}