ouisync/repository/
params.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use super::RepositoryMonitor;
use crate::{db, device_id::DeviceId, error::Result};
use metrics::{NoopRecorder, Recorder};
use state_monitor::{metrics::MetricsRecorder, StateMonitor};
use std::{
    borrow::Cow,
    path::{Path, PathBuf},
};

pub struct RepositoryParams<R> {
    store: Store,
    device_id: DeviceId,
    parent_monitor: Option<StateMonitor>,
    recorder: Option<R>,
}

impl<R> RepositoryParams<R> {
    pub fn with_device_id(self, device_id: DeviceId) -> Self {
        Self { device_id, ..self }
    }

    pub fn with_parent_monitor(self, parent_monitor: StateMonitor) -> Self {
        Self {
            parent_monitor: Some(parent_monitor),
            ..self
        }
    }

    pub fn with_recorder<S>(self, recorder: S) -> RepositoryParams<S> {
        RepositoryParams {
            store: self.store,
            device_id: self.device_id,
            parent_monitor: self.parent_monitor,
            recorder: Some(recorder),
        }
    }

    pub(super) async fn create(&self) -> Result<db::Pool, db::Error> {
        match &self.store {
            Store::Path(path) => db::create(path).await,
            #[cfg(test)]
            Store::Pool { pool, .. } => Ok(pool.clone()),
        }
    }

    pub(super) async fn open(&self) -> Result<db::Pool, db::Error> {
        match &self.store {
            Store::Path(path) => db::open(path).await,
            #[cfg(test)]
            Store::Pool { pool, .. } => Ok(pool.clone()),
        }
    }

    pub(super) fn device_id(&self) -> DeviceId {
        self.device_id
    }
}

impl<R> RepositoryParams<R>
where
    R: Recorder,
{
    pub(super) fn monitor(&self) -> RepositoryMonitor {
        let name = self.store.name();

        let monitor = if let Some(parent_monitor) = &self.parent_monitor {
            parent_monitor.make_child(name)
        } else {
            StateMonitor::make_root()
        };

        if let Some(recorder) = &self.recorder {
            RepositoryMonitor::new(monitor, recorder)
        } else {
            RepositoryMonitor::new(monitor.clone(), &MetricsRecorder::new(monitor))
        }
    }
}

impl RepositoryParams<NoopRecorder> {
    pub fn new(path: impl AsRef<Path>) -> Self {
        Self::with_store(Store::Path(path.as_ref().to_path_buf()))
    }

    #[cfg(test)]
    pub(crate) fn with_pool(pool: db::Pool, name: &str) -> Self {
        Self::with_store(Store::Pool {
            pool,
            name: name.to_owned(),
        })
    }

    fn with_store(store: Store) -> Self {
        Self {
            store,
            device_id: rand::random(),
            parent_monitor: None,
            recorder: None,
        }
    }
}

enum Store {
    Path(PathBuf),
    #[cfg(test)]
    Pool {
        pool: db::Pool,
        name: String,
    },
}

impl Store {
    fn name(&self) -> Cow<'_, str> {
        match self {
            Self::Path(path) => path.as_os_str().to_string_lossy(),
            #[cfg(test)]
            Self::Pool { name, .. } => name.into(),
        }
    }
}