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::LocalLb;
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::hasher::UuidIdentityHasherBuilder;
18use db_rs::{Db, List, LookupTable, Single, TxHandle};
19use db_rs_derive::Schema;
20use std::ops::{Deref, DerefMut};
21use std::sync::Arc;
22use tokio::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
23use uuid::Uuid;
24use web_time::{Duration, Instant};
25
26pub(crate) type LbDb = Arc<RwLock<CoreDb>>;
27// todo: limit visibility
28pub type CoreDb = CoreV4;
29
30#[derive(Schema, Debug)]
31#[cfg_attr(feature = "no-network", derive(Clone))]
32pub struct CoreV4 {
33    pub account: Single<Account>,
34    pub last_synced: Single<i64>,
35    pub root: Single<Uuid>,
36    pub local_metadata: LookupTable<Uuid, SignedMeta, UuidIdentityHasherBuilder>,
37    pub base_metadata: LookupTable<Uuid, SignedMeta, UuidIdentityHasherBuilder>,
38
39    /// map from pub key to username
40    pub pub_key_lookup: LookupTable<Owner, String>,
41
42    pub doc_events: List<DocEvent>,
43    pub id: Single<LbID>,
44    pub pinned_files: List<Uuid>,
45
46    /// Sentinel for `send_debug_info` throttling: the millisecond timestamp of the
47    /// most recent panic file we've already uploaded. `None` means we have never
48    /// sent debug info; `Some(0)` means we've sent before but no panic file existed.
49    pub last_extracted_panic: Single<i64>,
50}
51
52pub struct LbRO<'a> {
53    guard: RwLockReadGuard<'a, CoreDb>,
54}
55
56impl LbRO<'_> {
57    pub fn db(&self) -> &CoreDb {
58        self.guard.deref()
59    }
60}
61
62pub struct LbTx<'a> {
63    guard: RwLockWriteGuard<'a, CoreDb>,
64    tx: TxHandle,
65}
66
67impl LbTx<'_> {
68    pub fn db(&mut self) -> &mut CoreDb {
69        self.guard.deref_mut()
70    }
71
72    pub fn end(self) {
73        self.tx.drop_safely().unwrap();
74    }
75}
76
77impl LocalLb {
78    pub async fn ro_tx(&self) -> LbRO<'_> {
79        let start = Instant::now();
80
81        let guard = self.db.read().await;
82
83        if start.elapsed() > Duration::from_millis(100) {
84            warn!("readonly transaction lock acquisition took {:?}", start.elapsed());
85        }
86
87        LbRO { guard }
88    }
89
90    pub async fn begin_tx(&self) -> LbTx<'_> {
91        let start = Instant::now();
92
93        let mut guard = self.db.write().await;
94
95        if start.elapsed() > Duration::from_millis(100) {
96            warn!("readwrite transaction lock acquisition took {:?}", start.elapsed());
97        }
98
99        let tx = guard.begin_transaction().unwrap();
100
101        LbTx { guard, tx }
102    }
103}