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// }