lb_rs/io/
mod.rs

1//! Members of this model are concerned with the details of IO, generally
2//! disk and network. This is the module any on-disk migrations will live
3//! and ideas around network, disk, and memory caches will be expressed.
4//! Code here should not be platform dependent, and should strive to be
5//! suitable for a range of devices: iPhones with flaky networks to servers
6//! and workstations with excellent networks.
7
8pub mod docs;
9pub mod network;
10
11use crate::model::account::Account;
12use crate::model::file_metadata::Owner;
13use crate::model::signed_file::SignedFile;
14use crate::service::activity::DocEvent;
15use crate::Lb;
16use db_rs::{Db, List, LookupTable, Single, TxHandle};
17use db_rs_derive::Schema;
18use std::ops::{Deref, DerefMut};
19use std::sync::Arc;
20use tokio::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
21use uuid::Uuid;
22
23pub(crate) type LbDb = Arc<RwLock<CoreV3>>;
24// todo: limit visibility
25pub type CoreDb = CoreV3;
26
27#[derive(Schema, Debug)]
28#[cfg_attr(feature = "no-network", derive(Clone))]
29pub struct CoreV3 {
30    pub account: Single<Account>,
31    pub last_synced: Single<i64>,
32    pub root: Single<Uuid>,
33    pub local_metadata: LookupTable<Uuid, SignedFile>,
34    pub base_metadata: LookupTable<Uuid, SignedFile>,
35
36    /// map from pub key to username
37    pub pub_key_lookup: LookupTable<Owner, String>,
38
39    pub doc_events: List<DocEvent>,
40}
41
42pub struct LbRO<'a> {
43    guard: RwLockReadGuard<'a, CoreDb>,
44}
45
46impl LbRO<'_> {
47    pub fn db(&self) -> &CoreDb {
48        self.guard.deref()
49    }
50}
51
52pub struct LbTx<'a> {
53    guard: RwLockWriteGuard<'a, CoreDb>,
54    tx: TxHandle,
55}
56
57impl LbTx<'_> {
58    pub fn db(&mut self) -> &mut CoreDb {
59        self.guard.deref_mut()
60    }
61
62    pub fn end(self) {
63        self.tx.drop_safely().unwrap();
64    }
65}
66
67impl Lb {
68    pub async fn ro_tx(&self) -> LbRO<'_> {
69        let start = std::time::Instant::now();
70
71        // let guard = tokio::time::timeout(std::time::Duration::from_secs(1), self.db.read())
72        //     .await
73        //     .unwrap();
74
75        let guard = self.db.read().await;
76
77        if start.elapsed() > std::time::Duration::from_millis(100) {
78            warn!("readonly transaction lock acquisition took {:?}", start.elapsed());
79        }
80
81        LbRO { guard }
82    }
83
84    pub async fn begin_tx(&self) -> LbTx<'_> {
85        let start = std::time::Instant::now();
86
87        // let mut guard = tokio::time::timeout(std::time::Duration::from_secs(1), self.db.write())
88        //     .await
89        //     .unwrap();
90
91        let mut guard = self.db.write().await;
92
93        if start.elapsed() > std::time::Duration::from_millis(100) {
94            warn!("readwrite transaction lock acquisition took {:?}", start.elapsed());
95        }
96
97        let tx = guard.begin_transaction().unwrap();
98
99        LbTx { guard, tx }
100    }
101}