Skip to main content

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::Lb;
12use crate::model::account::Account;
13use crate::model::file_metadata::Owner;
14use crate::model::signed_meta::SignedMeta;
15use crate::service::activity::DocEvent;
16use crate::service::lb_id::LbID;
17use db_rs::{Db, List, LookupTable, Single, TxHandle};
18use db_rs_derive::Schema;
19use std::ops::{Deref, DerefMut};
20use std::sync::Arc;
21use tokio::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
22use uuid::Uuid;
23use web_time::{Duration, Instant};
24
25pub(crate) type LbDb = Arc<RwLock<CoreDb>>;
26// todo: limit visibility
27pub type CoreDb = CoreV4;
28
29#[derive(Schema, Debug)]
30#[cfg_attr(feature = "no-network", derive(Clone))]
31pub struct CoreV4 {
32    pub account: Single<Account>,
33    pub last_synced: Single<i64>,
34    pub root: Single<Uuid>,
35    pub local_metadata: LookupTable<Uuid, SignedMeta>,
36    pub base_metadata: LookupTable<Uuid, SignedMeta>,
37
38    /// map from pub key to username
39    pub pub_key_lookup: LookupTable<Owner, String>,
40
41    pub doc_events: List<DocEvent>,
42    pub id: Single<LbID>,
43}
44
45pub struct LbRO<'a> {
46    guard: RwLockReadGuard<'a, CoreDb>,
47}
48
49impl LbRO<'_> {
50    pub fn db(&self) -> &CoreDb {
51        self.guard.deref()
52    }
53}
54
55pub struct LbTx<'a> {
56    guard: RwLockWriteGuard<'a, CoreDb>,
57    tx: TxHandle,
58}
59
60impl LbTx<'_> {
61    pub fn db(&mut self) -> &mut CoreDb {
62        self.guard.deref_mut()
63    }
64
65    pub fn end(self) {
66        self.tx.drop_safely().unwrap();
67    }
68}
69
70impl Lb {
71    pub async fn ro_tx(&self) -> LbRO<'_> {
72        let start = Instant::now();
73
74        let guard = self.db.read().await;
75
76        if start.elapsed() > Duration::from_millis(100) {
77            warn!("readonly transaction lock acquisition took {:?}", start.elapsed());
78        }
79
80        LbRO { guard }
81    }
82
83    pub async fn begin_tx(&self) -> LbTx<'_> {
84        let start = Instant::now();
85
86        let mut guard = self.db.write().await;
87
88        if start.elapsed() > Duration::from_millis(100) {
89            warn!("readwrite transaction lock acquisition took {:?}", start.elapsed());
90        }
91
92        let tx = guard.begin_transaction().unwrap();
93
94        LbTx { guard, tx }
95    }
96}