saturn_cli/db/
remote.rs

1use crate::{
2    db::{unixfile::UnixFileLoader, RemoteClient, DB},
3    filenames::saturn_db,
4    record::{Record, RecurringRecord},
5};
6use anyhow::{anyhow, Result};
7use async_trait::async_trait;
8use serde::{Deserialize, Serialize};
9use std::collections::BTreeMap;
10
11#[derive(Debug, Clone)]
12pub struct RemoteDBClient<T: RemoteClient + Send + Sync + Default + std::fmt::Debug> {
13    client: T,
14    db: RemoteDB,
15}
16
17#[derive(Debug, Clone, Serialize, Deserialize, Default)]
18pub struct RemoteDB {
19    primary_key: u64,
20    recurrence_key: u64,
21    id_map: BTreeMap<String, u64>,
22    reverse_id_map: BTreeMap<u64, String>,
23    recurring_id_map: BTreeMap<String, u64>,
24    reverse_recurring_id_map: BTreeMap<u64, String>,
25    fields: BTreeMap<u64, crate::record::Fields>,
26    calendar_id: String,
27}
28
29impl<T: RemoteClient + Send + Sync + Default + std::fmt::Debug> RemoteDBClient<T> {
30    pub fn new(calendar_id: String, client: T) -> Self {
31        let db = RemoteDB::new(calendar_id);
32
33        // assuming this call convention is honored, client will always be "some" when actually
34        // used, and will only be empty when deserialized.
35        Self { client, db }
36    }
37}
38
39impl RemoteDB {
40    pub fn new(calendar_id: String) -> Self {
41        Self {
42            primary_key: 0,
43            recurrence_key: 0,
44            id_map: BTreeMap::default(),
45            reverse_id_map: BTreeMap::default(),
46            recurring_id_map: BTreeMap::default(),
47            reverse_recurring_id_map: BTreeMap::default(),
48            fields: BTreeMap::default(),
49            calendar_id,
50        }
51    }
52
53    pub fn add_internal(&mut self, primary_key: u64, remote_key: String) {
54        self.id_map.insert(remote_key.clone(), primary_key);
55        self.reverse_id_map.insert(primary_key, remote_key);
56    }
57
58    pub fn add(&mut self, primary_key: String, remote_key: u64) {
59        self.reverse_id_map.insert(remote_key, primary_key.clone());
60        self.id_map.insert(primary_key, remote_key);
61    }
62
63    pub fn add_recurring_internal(&mut self, primary_key: u64, remote_key: String) {
64        self.recurring_id_map
65            .insert(remote_key.clone(), primary_key);
66        self.reverse_recurring_id_map
67            .insert(primary_key, remote_key);
68    }
69
70    pub fn add_recurring(&mut self, primary_key: String, remote_key: u64) {
71        self.reverse_recurring_id_map
72            .insert(remote_key, primary_key.clone());
73        self.recurring_id_map.insert(primary_key, remote_key);
74    }
75
76    pub fn lookup_internal(&self, id: String) -> Option<u64> {
77        self.id_map.get(&id).cloned()
78    }
79
80    pub fn lookup(&self, id: u64) -> Option<String> {
81        self.reverse_id_map.get(&id).cloned()
82    }
83
84    pub fn recurring_lookup_internal(&self, id: String) -> Option<u64> {
85        self.recurring_id_map.get(&id).cloned()
86    }
87
88    pub fn recurring_lookup(&self, id: u64) -> Option<String> {
89        self.reverse_recurring_id_map.get(&id).cloned()
90    }
91
92    pub fn remove_by_internal_id(&mut self, id: u64) {
93        self.reverse_id_map
94            .remove(&id)
95            .map(|o| self.id_map.remove(&o));
96    }
97
98    pub fn remove_by_public_id(&mut self, id: String) {
99        self.id_map
100            .remove(&id)
101            .map(|o| self.reverse_id_map.remove(&o));
102    }
103
104    pub fn remove_recurring_by_internal_id(&mut self, id: u64) {
105        self.reverse_recurring_id_map
106            .remove(&id)
107            .map(|o| self.recurring_id_map.remove(&o));
108    }
109
110    pub fn remove_recurring_by_public_id(&mut self, id: String) {
111        self.recurring_id_map
112            .remove(&id)
113            .map(|o| self.reverse_recurring_id_map.remove(&o));
114    }
115}
116
117impl RemoteDB {
118    fn record_internal(&mut self, internal_key: String, pk: Option<u64>) -> Result<u64> {
119        let pk = if let Some(pk) = pk {
120            pk
121        } else {
122            self.next_key()
123        };
124
125        self.add_internal(pk, internal_key);
126        Ok(pk)
127    }
128
129    async fn record_updates(&mut self, mut records: Vec<Record>) -> Result<Vec<Record>> {
130        for record in &mut records {
131            if let Some(internal_recurrence_key) = record.internal_recurrence_key() {
132                if record.recurrence_key().is_none() {
133                    let key = self.next_recurrence_key();
134                    record.set_recurrence_key(Some(key));
135                    self.add_recurring(internal_recurrence_key, key);
136                }
137            }
138
139            if let Some(internal_key) = record.internal_key() {
140                if record.primary_key() == 0 {
141                    record.set_primary_key(self.record_internal(
142                        internal_key.clone(),
143                        self.lookup_internal(internal_key),
144                    )?);
145                }
146            }
147
148            if let Some(fields) = self.fields.get(&record.primary_key()) {
149                record.set_fields(fields.clone());
150            }
151        }
152
153        Ok(records)
154    }
155
156    async fn record_recurring_updates(
157        &mut self,
158        mut records: Vec<RecurringRecord>,
159    ) -> Result<Vec<RecurringRecord>> {
160        let mut v = Vec::new();
161        for record in &mut records {
162            if let Some(internal_recurrence_key) = record.internal_key() {
163                if let Some(internal) =
164                    self.recurring_lookup_internal(internal_recurrence_key.clone())
165                {
166                    record.set_recurrence_key(internal);
167                    record.record().set_recurrence_key(Some(internal));
168                    self.add_recurring(internal_recurrence_key.clone(), internal);
169                } else if record.recurrence_key() == 0 {
170                    let key = self.next_recurrence_key();
171                    record.set_recurrence_key(key);
172                    record.record().set_recurrence_key(Some(key));
173                    self.add_recurring(internal_recurrence_key.clone(), key);
174                } else {
175                    record.recurrence_key();
176                }
177            }
178
179            if let Some(internal_key) = record.record().internal_key() {
180                if record.record().primary_key() == 0 {
181                    record.record().set_primary_key(self.record_internal(
182                        internal_key.clone(),
183                        self.lookup_internal(internal_key),
184                    )?);
185                }
186            }
187
188            v.push(record.clone());
189        }
190
191        Ok(v)
192    }
193}
194
195#[async_trait]
196impl DB for RemoteDB {
197    async fn load(&mut self) -> Result<()> {
198        let db: Self = UnixFileLoader::new(&saturn_db()).load().await?;
199        self.primary_key = db.primary_key;
200        self.recurrence_key = db.recurrence_key;
201        self.id_map = db.id_map;
202        self.reverse_id_map = db.reverse_id_map;
203        self.recurring_id_map = db.recurring_id_map;
204        self.reverse_recurring_id_map = db.reverse_recurring_id_map;
205        self.fields = db.fields;
206        self.update_recurrence().await
207    }
208
209    async fn dump(&self) -> Result<()> {
210        UnixFileLoader::new(&saturn_db()).dump(self.clone()).await
211    }
212
213    fn primary_key(&self) -> u64 {
214        self.primary_key
215    }
216
217    fn set_primary_key(&mut self, primary_key: u64) {
218        self.primary_key = primary_key;
219    }
220
221    fn recurrence_key(&self) -> u64 {
222        self.recurrence_key
223    }
224
225    fn set_recurrence_key(&mut self, recurrence_key: u64) {
226        self.recurrence_key = recurrence_key;
227    }
228
229    async fn delete(&mut self, primary_key: u64) -> Result<()> {
230        self.remove_by_internal_id(primary_key);
231        Ok(())
232    }
233
234    async fn delete_recurrence(&mut self, recurrence_key: u64) -> Result<Vec<String>> {
235        self.remove_by_internal_id(recurrence_key);
236        self.remove_recurring_by_internal_id(recurrence_key);
237        // FIXME leaves a garbage record in the PK table
238        Ok(Vec::new())
239    }
240
241    async fn record(&mut self, _record: Record) -> Result<()> {
242        Ok(())
243    }
244
245    async fn record_recurrence(&mut self, _record: RecurringRecord) -> Result<()> {
246        Ok(())
247    }
248
249    async fn insert_record(&mut self, _record: Record) -> Result<()> {
250        Ok(())
251    }
252
253    async fn insert_recurrence(&mut self, _record: RecurringRecord) -> Result<()> {
254        Ok(())
255    }
256
257    async fn list_recurrence(&mut self) -> Result<Vec<RecurringRecord>> {
258        Ok(Default::default())
259    }
260
261    async fn update_recurrence(&mut self) -> Result<()> {
262        Ok(())
263    }
264
265    async fn list_today(&mut self, _include_completed: bool) -> Result<Vec<Record>> {
266        Ok(Default::default())
267    }
268
269    async fn list_all(&mut self, _include_completed: bool) -> Result<Vec<Record>> {
270        Ok(Default::default())
271    }
272
273    async fn events_now(
274        &mut self,
275        _last: chrono::Duration,
276        _include_completed: bool,
277    ) -> Result<Vec<Record>> {
278        Ok(Default::default())
279    }
280
281    async fn complete_task(&mut self, _primary_key: u64) -> Result<()> {
282        Ok(())
283    }
284
285    async fn get(&mut self, _primary_key: u64) -> Result<Record> {
286        Err(anyhow!("No Record Found"))
287    }
288
289    async fn get_recurring(&mut self, _primary_key: u64) -> Result<RecurringRecord> {
290        Err(anyhow!("No Record Found"))
291    }
292
293    async fn update(&mut self, _record: Record) -> Result<()> {
294        Ok(())
295    }
296
297    async fn update_recurring(&mut self, _record: RecurringRecord) -> Result<()> {
298        Ok(())
299    }
300}
301
302#[async_trait]
303impl<T: RemoteClient + Send + Sync + Default + std::fmt::Debug> DB for RemoteDBClient<T> {
304    async fn load(&mut self) -> Result<()> {
305        self.db.load().await
306    }
307
308    async fn dump(&self) -> Result<()> {
309        self.db.dump().await
310    }
311
312    fn primary_key(&self) -> u64 {
313        self.db.primary_key()
314    }
315
316    fn set_primary_key(&mut self, primary_key: u64) {
317        self.db.set_primary_key(primary_key)
318    }
319
320    fn recurrence_key(&self) -> u64 {
321        self.db.recurrence_key()
322    }
323
324    fn set_recurrence_key(&mut self, recurrence_key: u64) {
325        self.db.set_recurrence_key(recurrence_key);
326    }
327
328    async fn delete(&mut self, primary_key: u64) -> Result<()> {
329        let id = self
330            .db
331            .lookup(primary_key)
332            .map_or_else(|| Err(anyhow!("Invalid ID")), |k| Ok(k))?;
333
334        let calendar_id = self.db.calendar_id.clone();
335
336        self.client.delete(calendar_id, id).await?;
337        self.db.delete(primary_key).await?;
338        Ok(())
339    }
340
341    async fn delete_recurrence(&mut self, recurrence_key: u64) -> Result<Vec<String>> {
342        let id = self
343            .db
344            .recurring_lookup(recurrence_key)
345            .map_or_else(|| Err(anyhow!("Invalid ID")), |k| Ok(k))?;
346        let calendar_id = self.db.calendar_id.clone();
347
348        let list = self
349            .client
350            .delete_recurrence(calendar_id.clone(), id.clone())
351            .await?;
352        for item in list.iter() {
353            if let Some(id) = self.db.lookup_internal(item.clone()) {
354                let res = self.delete(id).await;
355                if matches!(res, Result::Err(_)) {
356                    break;
357                }
358            }
359        }
360
361        self.db.delete_recurrence(recurrence_key).await?;
362        if let Some(id) = self.db.lookup_internal(id) {
363            self.db.delete(id).await?;
364        }
365        // FIXME leaves a garbage record in the PK table
366        Ok(list)
367    }
368
369    async fn record(&mut self, record: Record) -> Result<()> {
370        if self.db.lookup(record.primary_key()).is_none() {
371            self.insert_record(record).await
372        } else {
373            Ok(())
374        }
375    }
376
377    async fn record_recurrence(&mut self, record: RecurringRecord) -> Result<()> {
378        if self.db.recurring_lookup(record.recurrence_key()).is_none() {
379            self.insert_recurrence(record).await
380        } else {
381            Ok(())
382        }
383    }
384
385    async fn insert_record(&mut self, record: Record) -> Result<()> {
386        let key = record.primary_key();
387        let calendar_id = self.db.calendar_id.clone();
388
389        let internal_key = self.client.record(calendar_id, record.clone()).await?;
390
391        self.db.add(internal_key, key);
392        self.db.fields.insert(key, record.fields());
393        Ok(())
394    }
395
396    async fn insert_recurrence(&mut self, mut record: RecurringRecord) -> Result<()> {
397        let calendar_id = self.db.calendar_id.clone();
398
399        let (key, recurrence_key) = self
400            .client
401            .record_recurrence(calendar_id, record.clone())
402            .await?;
403
404        record.set_internal_key(Some(key.clone()));
405        record
406            .record()
407            .set_internal_recurrence_key(Some(key.clone()));
408        record.record().set_internal_key(Some(key.clone()));
409        record.record().set_primary_key(self.next_key());
410
411        if record.recurrence_key() == 0 {
412            record.set_recurrence_key(self.next_recurrence_key());
413            record
414                .record()
415                .set_recurrence_key(Some(self.recurrence_key()));
416        }
417
418        self.db
419            .add_recurring(recurrence_key, record.recurrence_key());
420        Ok(())
421    }
422
423    async fn list_recurrence(&mut self) -> Result<Vec<RecurringRecord>> {
424        let calendar_id = self.db.calendar_id.clone();
425
426        self.db
427            .record_recurring_updates(self.client.list_recurrence(calendar_id).await?)
428            .await
429    }
430
431    async fn update_recurrence(&mut self) -> Result<()> {
432        let calendar_id = self.db.calendar_id.clone();
433
434        self.client.update_recurrence(calendar_id).await
435    }
436
437    async fn list_today(&mut self, include_completed: bool) -> Result<Vec<Record>> {
438        let calendar_id = self.db.calendar_id.clone();
439
440        self.db
441            .record_updates(
442                self.client
443                    .list_today(calendar_id, include_completed)
444                    .await?,
445            )
446            .await
447    }
448
449    async fn list_all(&mut self, include_completed: bool) -> Result<Vec<Record>> {
450        let calendar_id = self.db.calendar_id.clone();
451
452        self.db
453            .record_updates(self.client.list_all(calendar_id, include_completed).await?)
454            .await
455    }
456
457    async fn events_now(
458        &mut self,
459        last: chrono::Duration,
460        include_completed: bool,
461    ) -> Result<Vec<Record>> {
462        let calendar_id = self.db.calendar_id.clone();
463
464        self.db
465            .record_updates(
466                self.client
467                    .events_now(calendar_id, last, include_completed)
468                    .await?,
469            )
470            .await
471    }
472
473    async fn complete_task(&mut self, primary_key: u64) -> Result<()> {
474        let calendar_id = self.db.calendar_id.clone();
475
476        self.client.complete_task(calendar_id, primary_key).await
477    }
478
479    async fn get(&mut self, primary_key: u64) -> Result<Record> {
480        let calendar_id = self.db.calendar_id.clone();
481        let event_id = self
482            .db
483            .lookup(primary_key)
484            .ok_or(anyhow!("No Record Found"))?;
485        let mut rec = self.client.get(calendar_id, event_id).await?;
486        rec.set_primary_key(primary_key);
487        if let Some(fields) = self.db.fields.get(&primary_key) {
488            rec.set_fields(fields.clone());
489        }
490        Ok(rec)
491    }
492
493    async fn get_recurring(&mut self, recurrence_key: u64) -> Result<RecurringRecord> {
494        let calendar_id = self.db.calendar_id.clone();
495        let event_id = self
496            .db
497            .recurring_lookup(recurrence_key)
498            .ok_or(anyhow!("No Record Found"))?;
499        let mut rec = self
500            .client
501            .get_recurring(calendar_id, event_id.clone())
502            .await?;
503        let primary_key = self.db.lookup_internal(event_id).unwrap_or(0);
504        rec.record().set_primary_key(primary_key);
505        rec.record().set_recurrence_key(Some(recurrence_key));
506        rec.set_recurrence_key(recurrence_key);
507        Ok(rec)
508    }
509
510    async fn update(&mut self, record: Record) -> Result<()> {
511        let calendar_id = self.db.calendar_id.clone();
512        self.db.fields.insert(record.primary_key(), record.fields());
513        self.client.update(calendar_id, record).await
514    }
515
516    async fn update_recurring(&mut self, record: RecurringRecord) -> Result<()> {
517        let calendar_id = self.db.calendar_id.clone();
518        self.client.update_recurring(calendar_id, record).await
519    }
520}