Skip to main content

vantage_dataset/im/
dataset_writable.rs

1use async_trait::async_trait;
2use vantage_types::{Entity, Record, TryFromRecord};
3
4use crate::{
5    im::ImTable,
6    traits::{Result, WritableDataSet},
7};
8
9#[async_trait]
10impl<E> WritableDataSet<E> for ImTable<E>
11where
12    E: Entity + Clone + Send + Sync,
13    <E as TryFromRecord<serde_json::Value>>::Error: std::fmt::Debug,
14{
15    async fn insert(&self, id: &Self::Id, entity: &E) -> Result<E> {
16        let mut table = self.data_source.get_or_create_table(&self.table_name);
17
18        // Check if record already exists (idempotent behavior)
19        if let Some(existing_record) = table.get(id) {
20            // Return existing entity
21            // Add the id field to the record for conversion
22            let mut record_with_id = existing_record.clone();
23            record_with_id.insert("id".to_string(), serde_json::Value::String(id.clone()));
24
25            let existing_entity = E::try_from_record(&record_with_id).map_err(|e| {
26                vantage_core::util::error::vantage_error!(
27                    "Failed to convert record to entity: {:?}",
28                    e
29                )
30            })?;
31            return Ok(existing_entity);
32        }
33
34        // Convert entity to record for storage (remove id field since it's in the key)
35        let mut record: Record<serde_json::Value> = entity.clone().into_record();
36        record.shift_remove("id");
37
38        table.insert(id.clone(), record);
39        self.data_source.update_table(&self.table_name, table);
40
41        Ok(entity.clone())
42    }
43
44    async fn replace(&self, id: &Self::Id, entity: &E) -> Result<E> {
45        let mut table = self.data_source.get_or_create_table(&self.table_name);
46
47        // Convert entity to record for storage (remove id field since it's in the key)
48        let mut record: Record<serde_json::Value> = entity.clone().into_record();
49        record.shift_remove("id");
50
51        table.insert(id.clone(), record);
52        self.data_source.update_table(&self.table_name, table);
53
54        Ok(entity.clone())
55    }
56
57    async fn patch(&self, id: &Self::Id, partial: &E) -> Result<E> {
58        let mut table = self.data_source.get_or_create_table(&self.table_name);
59
60        // Check if record exists
61        let mut existing_record = table
62            .get(id)
63            .ok_or_else(|| {
64                vantage_core::util::error::vantage_error!("Record with id '{}' not found", id)
65            })?
66            .clone();
67
68        // Convert partial entity to record
69        let partial_record: Record<serde_json::Value> = partial.clone().into_record();
70
71        // Merge the partial fields into the existing record
72        for (key, value) in partial_record.iter() {
73            if key != "id" {
74                // Don't allow patching the id field
75                existing_record.insert(key.clone(), value.clone());
76            }
77        }
78
79        table.insert(id.clone(), existing_record.clone());
80        self.data_source.update_table(&self.table_name, table);
81
82        // Return the merged entity
83        let mut record_with_id = existing_record;
84        record_with_id.insert("id".to_string(), serde_json::Value::String(id.clone()));
85
86        let merged_entity = E::try_from_record(&record_with_id).map_err(|e| {
87            vantage_core::util::error::vantage_error!("Failed to convert record to entity: {:?}", e)
88        })?;
89        Ok(merged_entity)
90    }
91}
92
93// Tests are in tests/im_dataset.rs integration tests