| 39 | } |
| 40 | |
| 41 | pub(super) async fn graph_insert_edge_impl( |
| 42 | &self, |
| 43 | collection: &str, |
| 44 | from: &NodeId, |
| 45 | to: &NodeId, |
| 46 | edge_type: &str, |
| 47 | properties: Option<Document>, |
| 48 | ) -> NodeDbResult<EdgeId> { |
| 49 | // Convert the document fields to a `serde_json::Value` via the |
| 50 | // type-level `From<nodedb_types::Value>` conversion — no runtime JSON |
| 51 | // serialization, and infallible, so properties are never silently |
| 52 | // dropped on a serializer error. |
| 53 | let props_json = properties.map(|d| { |
| 54 | serde_json::Value::Object( |
| 55 | d.fields |
| 56 | .into_iter() |
| 57 | .map(|(k, v)| (k, serde_json::Value::from(v))) |
| 58 | .collect(), |
| 59 | ) |
| 60 | }); |
| 61 | let mut conn = self.pool.acquire().await?; |
| 62 | conn.send( |
| 63 | OpCode::EdgePut, |
| 64 | TextFields { |
| 65 | collection: Some(collection.to_string()), |
| 66 | from_node: Some(from.as_str().to_string()), |
| 67 | to_node: Some(to.as_str().to_string()), |
| 68 | edge_type: Some(edge_type.to_string()), |
| 69 | properties: props_json, |
| 70 | ..Default::default() |
| 71 | }, |
| 72 | ) |
| 73 | .await?; |
| 74 | EdgeId::try_first(from.clone(), to.clone(), edge_type) |
| 75 | .map_err(|e| NodeDbError::storage(format!("invalid edge label: {e}"))) |
| 76 | } |
| 77 | |
| 78 | pub(super) async fn graph_delete_edge_impl( |
| 79 | &self, |