Skip to main content

bones_core/event/
migrate.rs

1//! Event format migration helpers.
2//!
3//! This module provides version-specific transforms to upgrade events parsed
4//! from older shard formats into the current in-memory [`Event`] shape.
5
6use anyhow::{Result, anyhow};
7
8use crate::event::{CURRENT_VERSION, Event};
9
10/// Raw event representation parsed from an older format version.
11///
12/// Today v1 and current share the same logical event schema, so this is an
13/// alias. Future format versions may replace this with a distinct type.
14pub type RawEvent = Event;
15
16/// Apply version-specific transforms to an event parsed from an older format.
17///
18/// Returns the event upgraded to the current-version representation.
19///
20/// # Errors
21///
22/// Returns an error if `from_version` is not a recognized format version.
23pub fn migrate_event(event: RawEvent, from_version: u32) -> Result<Event> {
24    match from_version {
25        1 => migrate_v1_to_current(event),
26        v if v == CURRENT_VERSION => Ok(event),
27        v => Err(anyhow!("unknown format version {v}")),
28    }
29}
30
31/// V1 -> current migration.
32///
33/// Currently a no-op passthrough because v1 is the active format.
34const fn migrate_v1_to_current(event: RawEvent) -> Result<Event> {
35    Ok(event)
36}
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41    use crate::event::{CreateData, EventData, EventType};
42    use crate::model::item::{Kind, Size, Urgency};
43    use crate::model::item_id::ItemId;
44    use std::collections::BTreeMap;
45
46    fn sample_event() -> Event {
47        Event {
48            wall_ts_us: 1_700_000_000_000_000,
49            agent: "agent-1".into(),
50            itc: "itc:AQ".into(),
51            parents: vec![],
52            event_type: EventType::Create,
53            item_id: ItemId::new_unchecked("bn-a1b"),
54            data: EventData::Create(CreateData {
55                title: "Sample".into(),
56                kind: Kind::Task,
57                size: Some(Size::M),
58                urgency: Urgency::Default,
59                labels: vec!["compatibility".into()],
60                parent: None,
61                causation: None,
62                description: None,
63                extra: BTreeMap::new(),
64            }),
65            event_hash: "blake3:deadbeef".into(),
66        }
67    }
68
69    #[test]
70    fn migrate_current_version_passthrough() {
71        let event = sample_event();
72        let migrated = migrate_event(event.clone(), CURRENT_VERSION).expect("migrate");
73        assert_eq!(migrated, event);
74    }
75
76    #[test]
77    fn migrate_v1_passthrough() {
78        let event = sample_event();
79        let migrated = migrate_event(event.clone(), 1).expect("migrate");
80        assert_eq!(migrated, event);
81    }
82
83    #[test]
84    fn migrate_unknown_version_errors() {
85        let event = sample_event();
86        let err = migrate_event(event, CURRENT_VERSION + 1).expect_err("must fail");
87        assert!(err.to_string().contains("unknown format version"));
88    }
89}