• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

getdozer / dozer / 4116183752

pending completion
4116183752

push

github

GitHub
refactor: Make `LmdbRoCache` and `LmdbRwCache` `Send` and `Sync` (#821)

790 of 790 new or added lines in 44 files covered. (100.0%)

23005 of 33842 relevant lines covered (67.98%)

56312.85 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

66.9
/dozer-cache/src/cache/lmdb/utils.rs
1
use std::{fs, ops::Deref};
2

3
use crate::errors::CacheError;
4
use dozer_storage::{
5
    lmdb::EnvironmentFlags,
6
    lmdb_storage::{LmdbEnvironmentManager, LmdbEnvironmentOptions},
7
};
8
use tempdir::TempDir;
9

10
use super::{CacheOptions, CacheOptionsKind};
×
11

×
12
pub fn init_env(options: &CacheOptions) -> Result<LmdbEnvironmentManager, CacheError> {
105✔
13
    match &options.kind {
105✔
14
        CacheOptionsKind::Write(write_options) => {
104✔
15
            let (base_path, name, _temp_dir) = match &options.common.path {
104✔
16
                None => {
×
17
                    let base_path =
103✔
18
                        TempDir::new("dozer").map_err(|e| CacheError::Internal(Box::new(e)))?;
103✔
19
                    (
103✔
20
                        base_path.path().to_path_buf(),
103✔
21
                        "dozer-cache",
103✔
22
                        Some(base_path),
103✔
23
                    )
103✔
24
                }
×
25
                Some((base_path, name)) => {
1✔
26
                    fs::create_dir_all(base_path).map_err(|e| CacheError::Internal(Box::new(e)))?;
1✔
27
                    (base_path.clone(), name.deref(), None)
1✔
28
                }
×
29
            };
×
30

×
31
            let options = LmdbEnvironmentOptions::new(
104✔
32
                options.common.max_db_size,
104✔
33
                options.common.max_readers,
104✔
34
                write_options.max_size,
104✔
35
                EnvironmentFlags::empty(),
104✔
36
            );
104✔
37

104✔
38
            Ok(LmdbEnvironmentManager::create(&base_path, name, options)?)
104✔
39
        }
×
40
        CacheOptionsKind::ReadOnly(_) => {
×
41
            let (base_path, name) = options
1✔
42
                .common
1✔
43
                .path
1✔
44
                .as_ref()
1✔
45
                .ok_or(CacheError::PathNotInitialized)?;
1✔
46

×
47
            let env_options = LmdbEnvironmentOptions {
1✔
48
                max_dbs: options.common.max_db_size,
1✔
49
                max_readers: options.common.max_readers,
1✔
50
                flags: EnvironmentFlags::READ_ONLY,
1✔
51
                ..Default::default()
1✔
52
            };
1✔
53

1✔
54
            Ok(LmdbEnvironmentManager::create(
1✔
55
                base_path,
1✔
56
                name,
1✔
57
                env_options,
1✔
58
            )?)
1✔
59
        }
60
    }
61
}
105✔
62

63
#[cfg(test)]
64
mod tests {
65
    use dozer_storage::lmdb::{Cursor, DatabaseFlags, RoCursor, Transaction, WriteFlags};
66
    use dozer_types::types::Field;
×
67

×
68
    use crate::cache::lmdb::{utils::init_env, CacheOptions};
×
69

70
    fn cursor_dump(mut cursor: RoCursor) -> Vec<(&[u8], &[u8])> {
1✔
71
        cursor
1✔
72
            .iter_dup()
1✔
73
            .flatten()
1✔
74
            .collect::<dozer_storage::lmdb::Result<Vec<_>>>()
1✔
75
            .unwrap()
1✔
76
    }
1✔
77

×
78
    #[test]
1✔
79
    fn duplicate_test_nested() {
1✔
80
        let options = CacheOptions::default();
1✔
81
        let mut env = init_env(&options).unwrap();
1✔
82

1✔
83
        let db = env
1✔
84
            .create_database(
1✔
85
                Some("test"),
1✔
86
                Some(DatabaseFlags::DUP_SORT | DatabaseFlags::INTEGER_KEY),
1✔
87
            )
1✔
88
            .unwrap();
1✔
89

1✔
90
        let txn = env.create_txn().unwrap();
1✔
91
        let mut master_txn = txn.write();
1✔
92
        let txn = master_txn.txn_mut();
1✔
93

1✔
94
        let mut c_txn = txn.begin_nested_txn().unwrap();
1✔
95

1✔
96
        let items: Vec<(i64, &[u8])> = vec![
1✔
97
            (1, b"a"),
1✔
98
            (2, b"a"),
1✔
99
            (3, b"a"),
1✔
100
            (1, b"b"),
1✔
101
            (2, b"b"),
1✔
102
            (3, b"b"),
1✔
103
            (1, b"c"),
1✔
104
            (2, b"c"),
1✔
105
            (3, b"c"),
1✔
106
            (1, b"e"),
1✔
107
            (2, b"e"),
1✔
108
            (3, b"e"),
1✔
109
        ];
1✔
110
        for (key, data) in &items {
13✔
111
            let key = [
12✔
112
                "idx".as_bytes().to_vec(),
12✔
113
                Field::Int(*key).encode(),
12✔
114
                key.to_be_bytes().to_vec(),
12✔
115
            ]
12✔
116
            .join("#".as_bytes());
12✔
117
            c_txn.put(db, &key, data, WriteFlags::empty()).unwrap();
12✔
118
        }
12✔
119
        c_txn.commit().unwrap();
1✔
120
        master_txn.commit_and_renew().unwrap();
1✔
121

1✔
122
        let rtxn = master_txn.txn();
1✔
123

1✔
124
        let cursor = rtxn.open_ro_cursor(db).unwrap();
1✔
125
        let vals = cursor_dump(cursor);
1✔
126
        assert_eq!(vals.len(), items.len(), "must have duplicate records");
1✔
127
    }
1✔
128
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc