jellyflow_runtime/io/files/
graph.rs1use std::path::Path;
2
3use jellyflow_core::core::{Graph, GraphId};
4use serde::{Deserialize, Serialize};
5
6pub const GRAPH_FILE_VERSION: u32 = 1;
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct GraphFileV1 {
14 pub graph_id: GraphId,
16 pub graph_version: u32,
18 pub graph: Graph,
20}
21
22impl GraphFileV1 {
23 pub fn from_graph(graph: Graph) -> Self {
25 Self {
26 graph_id: graph.graph_id,
27 graph_version: GRAPH_FILE_VERSION,
28 graph,
29 }
30 }
31
32 pub fn validate(&self) -> Result<(), GraphFileError> {
34 if self.graph_id != self.graph.graph_id {
35 return Err(GraphFileError::InconsistentGraphId);
36 }
37 Ok(())
38 }
39
40 pub fn load_json(path: impl AsRef<Path>) -> Result<Self, GraphFileError> {
42 let path = path.as_ref();
43 let bytes = std::fs::read(path).map_err(|source| GraphFileError::Read {
44 path: path.display().to_string(),
45 source,
46 })?;
47
48 let v = serde_json::from_slice::<Self>(&bytes).map_err(|source| GraphFileError::Parse {
49 path: path.display().to_string(),
50 source,
51 })?;
52 v.validate()?;
53 Ok(v)
54 }
55
56 pub fn load_json_if_exists(path: impl AsRef<Path>) -> Result<Option<Self>, GraphFileError> {
58 let path = path.as_ref();
59 if !path.exists() {
60 return Ok(None);
61 }
62 Self::load_json(path).map(Some)
63 }
64
65 pub fn save_json(&self, path: impl AsRef<Path>) -> Result<(), GraphFileError> {
67 let path = path.as_ref();
68 if let Some(parent) = path.parent() {
69 std::fs::create_dir_all(parent).map_err(|source| GraphFileError::Write {
70 path: path.display().to_string(),
71 source,
72 })?;
73 }
74 let bytes =
75 serde_json::to_vec_pretty(self).map_err(|source| GraphFileError::Serialize {
76 path: path.display().to_string(),
77 source,
78 })?;
79 std::fs::write(path, bytes).map_err(|source| GraphFileError::Write {
80 path: path.display().to_string(),
81 source,
82 })
83 }
84}
85
86#[derive(Debug, thiserror::Error)]
88pub enum GraphFileError {
89 #[error("failed to read graph file: {path}")]
91 Read {
92 path: String,
93 source: std::io::Error,
94 },
95 #[error("failed to parse graph file JSON: {path}")]
97 Parse {
98 path: String,
99 source: serde_json::Error,
100 },
101 #[error("failed to write graph file: {path}")]
103 Write {
104 path: String,
105 source: std::io::Error,
106 },
107 #[error("failed to serialize graph file JSON: {path}")]
109 Serialize {
110 path: String,
111 source: serde_json::Error,
112 },
113 #[error("graph file wrapper graph_id does not match graph.graph_id")]
115 InconsistentGraphId,
116}