ft_api/
bulk_update.rs

1#[derive(serde_derive::Serialize)]
2struct BulkUpdateInput {
3    collection: String,
4    auth_code: String,
5    current_hash: String,
6    new_hash: String,
7    repo: String,
8    files: Vec<Action>,
9}
10
11#[derive(serde_derive::Serialize)]
12struct File {
13    id: String,
14    content: String,
15}
16
17pub enum Error {
18    RealmClientError(realm_client::Error),
19    ContentMismatch { id: String },
20}
21
22#[allow(clippy::too_many_arguments)]
23pub fn bulk_update(
24    collection: &str,
25    current_hash: &str,
26    new_hash: &str,
27    repo: &str,
28    files: Vec<Action>,
29    auth_code: &str,
30    platform: String,
31    client_version: String,
32) -> realm_client::Result<()> {
33    let url = format!("/{}/~/bulk-update/", collection);
34
35    let update = BulkUpdateInput {
36        collection: collection.trim().to_string(),
37        auth_code: auth_code.trim().to_string(),
38        current_hash: current_hash.trim().to_string(),
39        new_hash: new_hash.trim().to_string(),
40        repo: repo.trim().to_string(),
41        files,
42    };
43
44    #[derive(serde_derive::Serialize)]
45    struct UpdatedWrapper {
46        data: BulkUpdateInput,
47        platform: String,
48        client_version: String,
49    }
50
51    realm_client::action::<crate::sync_status::Status, _>(
52        &url,
53        UpdatedWrapper {
54            data: update,
55            platform,
56            client_version,
57        },
58        Some("bulk_update".to_string()),
59    )?;
60    Ok(())
61}
62
63#[derive(serde_derive::Serialize, Debug)]
64#[serde(tag = "type")]
65pub enum Action {
66    Updated { id: String, content: String },
67    Added { id: String, content: String },
68    Deleted { id: String },
69}
70
71impl Action {
72    pub fn id(&self) -> &str {
73        match self {
74            Self::Updated { id, .. } => id,
75            Self::Added { id, .. } => id,
76            Self::Deleted { id } => id,
77        }
78    }
79
80    pub fn is_updated(&self) -> bool {
81        matches!(self, Self::Updated { .. })
82    }
83
84    pub fn is_added(&self) -> bool {
85        matches!(self, Self::Added { .. })
86    }
87
88    pub fn is_deleted(&self) -> bool {
89        matches!(self, Self::Deleted { .. })
90    }
91}
92
93// fn digest(actions: Vec<Action>) -> Vec<Action> {
94//     // more than one Updated with the same id, ensure each content is exactly same and merge
95//     // into one
96//     //
97//     let updated: Vec<_> = actions
98//         .iter()
99//         .filter(|x| x.is_updated())
100//         .filter_map(|x| {
101//             if let Action::Updated { id, content } = x {
102//                 Some((id, content))
103//             } else {
104//                 None
105//             }
106//         })
107//         .collect();
108//
109//     let updated_map: std::collections::HashMap<_, _> = updated.clone().into_iter().collect();
110//
111//     for (id, content) in updated.iter() {
112//         if let Some(c) = updated_map.get(id) {
113//             if !c.eq(content) {
114//                 println!("Updated action: content is not same for id: {}", id)
115//                 // return error
116//             }
117//         }
118//     }
119//
120//     // TODO: collect unique updated ID's
121//
122//     // more than one Added with the same id, ensure each content is exactly same and merge
123//     // into one
124//     //
125//
126//     let added: Vec<_> = actions
127//         .iter()
128//         .filter(|x| x.is_added())
129//         .filter_map(|x| {
130//             if let Action::Added { id, content } = x {
131//                 Some((id, content))
132//             } else {
133//                 None
134//             }
135//         })
136//         .collect();
137//
138//     let added_map: std::collections::HashMap<_, _> = added.clone().into_iter().collect();
139//
140//     for (id, content) in added.iter() {
141//         if let Some(c) = added_map.get(id) {
142//             if !c.eq(content) {
143//                 println!("Added action: content is not same for id: {}", id)
144//                 // return error
145//             }
146//         }
147//     }
148//     // TODO: collect unique added ID's
149//
150//     // if more than one Deleted with the same id, merge into one
151//     //
152//
153//     let deleted: Vec<_> = actions
154//         .iter()
155//         .filter(|x| x.is_deleted())
156//         .filter_map(|x| {
157//             if let Action::Deleted { id } = x {
158//                 Some(id)
159//             } else {
160//                 None
161//             }
162//         })
163//         .collect();
164//
165//     let _deleted: std::collections::HashMap<_, _> =
166//         deleted.clone().into_iter().map(|x| (x, true)).collect();
167//
168//     // TODO: collect unique deleted ID's
169//
170//     // if both Updated and Added have same id, ensure content matches and than merge Updated
171//     //
172//
173//     // if something is added and deleted, return Error::AddedAndDeleted {id: ""}
174//     //
175//     // if content is both Updated and Deleted, only send Deleted
176//     //
177//     // Note: If content mismatches, we will return Error::ContentMismatch
178//     vec![]
179// }