DB

Struct DB 

Source
pub struct DB {
    pub path: PathBuf,
    /* private fields */
}
Expand description

This is the main struct which represents the database.

This struct holds the connection to the sled database and provides safe, high-level access to the various data trees. It manages a background thread for handling TTL (Time-To-Live) expirations automatically.

When this struct is dropped, it will signal the background thread to shut down and wait for it to finish gracefully.

This struct also holds 2 Arcsled::Tree directly instead of a single sled::Db, since almost all of the functions uses the tree directly which requires the sled::Db to constantly open each trees. Passing trees from the struct deletes the constant need to open the trees

Fields§

§path: PathBuf

Path to the database

Implementations§

Source§

impl DB

Source

pub fn iter(&mut self) -> DataIter

This function returns the iterator of the database, which will contain a key and its corresponding value in each iteration, (key, value).

Source§

impl DB

Source

pub fn transaction<F>(&self, f: F) -> Result<(), TransientError>
where F: Fn(&mut TransactionalGuard<'_>) -> Result<(), Box<dyn Error>>,

Examples found in repository?
examples/transaction.rs (lines 25-52)
8fn main() -> Result<(), Box<dyn Error>> {
9    // 1. Setup a temporary database for the example.
10    let temp_dir = tempdir()?;
11    let db = DB::new(temp_dir.path())?;
12
13    println!("Database created successfully.");
14
15    // 2. Set the initial state for two user accounts.
16    db.set("user:alice", "100", None)?;
17    db.set("user:bob", "50", None)?;
18
19    println!("Initial state:");
20    println!("  - Alice's balance: {}", db.get("user:alice")?.unwrap());
21    println!("  - Bob's balance:   {}", db.get("user:bob")?.unwrap());
22    println!("\nAttempting to transfer 20 from Alice to Bob...");
23
24    // 3. Run the atomic transfer inside a transaction.
25    let transaction_result = db.transaction(|tx| {
26        // Get the current balances.
27        let alice_balance_str = tx.get("user:alice")?.unwrap();
28        let bob_balance_str = tx.get("user:bob")?.unwrap();
29
30        let mut alice_balance: u64 = alice_balance_str.parse()?;
31        let mut bob_balance: u64 = bob_balance_str.parse()?;
32
33        let transfer_amount = 20;
34
35        // Check if the transfer is possible.
36        if alice_balance < transfer_amount {
37            // By returning an error, we abort the entire transaction.
38            // No changes will be saved.
39            return Err(Box::from("Alice has insufficient funds!"));
40        }
41
42        // Perform the transfer.
43        alice_balance -= transfer_amount;
44        bob_balance += transfer_amount;
45
46        // Save the new balances.
47        tx.set("user:alice", &alice_balance.to_string(), None)?;
48        tx.set("user:bob", &bob_balance.to_string(), None)?;
49
50        // Return Ok to commit the transaction.
51        Ok(())
52    });
53
54    // 4. Check if the transaction succeeded.
55    if let Err(e) = transaction_result {
56        println!("\nTransaction failed: {}", e);
57    } else {
58        println!("\nTransaction successful!");
59    }
60
61    // 5. Verify the final state of the database.
62    // The balances should be updated because the transaction succeeded.
63    println!("\nFinal state:");
64    println!("  - Alice's balance: {}", db.get("user:alice")?.unwrap());
65    println!("  - Bob's balance:   {}", db.get("user:bob")?.unwrap());
66
67    assert_eq!(db.get("user:alice")?.unwrap(), "80");
68    assert_eq!(db.get("user:bob")?.unwrap(), "70");
69
70    Ok(())
71}
Source§

impl DB

Source

pub fn new(path: &Path) -> Result<DB, TransientError>

Creates a new DB instance or opens an existing one at the specified path.

This function initializes the underlying sled database, opens the required data trees (data_tree, meta_tree, ttl_tree), and spawns a background thread to handle TTL expirations.

§Errors

Returns a sled::Error if the database cannot be opened at the given path.

Examples found in repository?
examples/metadata.rs (line 6)
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6    let db = DB::new(Path::new("./my_database"))?;
7
8    db.set("user:2", "Bob", None)?;
9
10    // Increment the frequency counter
11    db.increment_frequency("user:2")?;
12
13    // Get the metadata for the key
14    if let Some(meta) = db.get_metadata("user:2")? {
15        println!("'user:2' has been accessed {} time(s)", meta.freq);
16        // "'user:2' has been accessed 1 time(s)"
17    }
18
19    Ok(())
20}
More examples
Hide additional examples
examples/basic_operations.rs (line 8)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7    // 1. Open the database. It will be created if it doesn't exist.
8    let db = DB::new(Path::new("./my_database"))?;
9
10    // 2. Set a value with a 10-second TTL.
11    db.set("user:1", "Alice", Some(Duration::from_secs(10)))?;
12
13    // 3. Get the value back.
14    if let Some(value) = db.get("user:1")? {
15        println!("Found value: {}", value); // "Found value: Alice"
16    }
17
18    // 4. Remove the data.
19    db.remove("user:1")?;
20
21    Ok(())
22}
examples/prometheus_track.rs (line 48)
41fn main() -> Result<(), Box<dyn std::error::Error>> {
42    thread::spawn(server_main);
43
44    // Let the thread build the app first
45    // and Let prometheus scrape once
46    sleep(Duration::new(15, 0));
47
48    let db = DB::new(Path::new("./databasetest")).unwrap();
49
50    db.set("H", "haha", None).unwrap();
51    db.set("HAHAHHAH", "Skib", None).unwrap();
52    db.set("HI", "h", None).unwrap();
53    db.set("Chronos", "Temporal", None).unwrap();
54    db.set("pop", "HAHAHAHH", Some(Duration::new(0, 100000)))
55        .unwrap();
56    for i in 0..1000 {
57        db.get("HI").unwrap();
58        db.set(&format!("{i}"), "h", None).unwrap();
59    }
60    db.backup_to(Path::new("./backup/")).unwrap();
61
62    Ok(())
63}
examples/concurrency.rs (line 7)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7    let db = Arc::new(DB::new("./my_database".as_ref())?);
8    db.set("concurrent_key", "initial_value", None)?;
9
10    let mut handles = vec![];
11    for _ in 0..10 {
12        let db_clone = Arc::clone(&db);
13        let handle = thread::spawn(move || {
14            for _ in 0..100 {
15                db_clone.increment_frequency("concurrent_key").unwrap();
16            }
17        });
18        handles.push(handle);
19    }
20
21    for handle in handles {
22        handle.join().unwrap();
23    }
24
25    let final_meta = db.get_metadata("concurrent_key")?.unwrap();
26    println!("Final frequency: {}", final_meta.freq); // "Final frequency: 1000"
27
28    Ok(())
29}
examples/ttl.rs (line 8)
7fn main() -> Result<(), Box<dyn std::error::Error>> {
8    let db = DB::new(Path::new("./my_database"))?;
9
10    // Set a key with a 2-second TTL
11    db.set("session:123", "user_token", Some(Duration::from_secs(2)))?;
12    println!("'session:123' is set.");
13
14    // The key exists initially
15    assert!(db.get("session:123")?.is_some());
16
17    // Wait for the TTL to expire
18    sleep(Duration::from_secs(3));
19
20    // The key should now be gone
21    assert!(db.get("session:123")?.is_none());
22    println!("'session:123' has expired.");
23
24    // You can also update a key to make it permanent
25    db.set(
26        "user:permanent",
27        "This will last forever",
28        Some(Duration::from_secs(1))
29    )?;
30    db.set("user:permanent", "This will last forever", None)?; // Remove the TTL
31
32    sleep(Duration::from_secs(2));
33    assert!(db.get("user:permanent")?.is_some());
34    println!("'user:permanent' is still here.");
35
36    Ok(())
37}
examples/transaction.rs (line 11)
8fn main() -> Result<(), Box<dyn Error>> {
9    // 1. Setup a temporary database for the example.
10    let temp_dir = tempdir()?;
11    let db = DB::new(temp_dir.path())?;
12
13    println!("Database created successfully.");
14
15    // 2. Set the initial state for two user accounts.
16    db.set("user:alice", "100", None)?;
17    db.set("user:bob", "50", None)?;
18
19    println!("Initial state:");
20    println!("  - Alice's balance: {}", db.get("user:alice")?.unwrap());
21    println!("  - Bob's balance:   {}", db.get("user:bob")?.unwrap());
22    println!("\nAttempting to transfer 20 from Alice to Bob...");
23
24    // 3. Run the atomic transfer inside a transaction.
25    let transaction_result = db.transaction(|tx| {
26        // Get the current balances.
27        let alice_balance_str = tx.get("user:alice")?.unwrap();
28        let bob_balance_str = tx.get("user:bob")?.unwrap();
29
30        let mut alice_balance: u64 = alice_balance_str.parse()?;
31        let mut bob_balance: u64 = bob_balance_str.parse()?;
32
33        let transfer_amount = 20;
34
35        // Check if the transfer is possible.
36        if alice_balance < transfer_amount {
37            // By returning an error, we abort the entire transaction.
38            // No changes will be saved.
39            return Err(Box::from("Alice has insufficient funds!"));
40        }
41
42        // Perform the transfer.
43        alice_balance -= transfer_amount;
44        bob_balance += transfer_amount;
45
46        // Save the new balances.
47        tx.set("user:alice", &alice_balance.to_string(), None)?;
48        tx.set("user:bob", &bob_balance.to_string(), None)?;
49
50        // Return Ok to commit the transaction.
51        Ok(())
52    });
53
54    // 4. Check if the transaction succeeded.
55    if let Err(e) = transaction_result {
56        println!("\nTransaction failed: {}", e);
57    } else {
58        println!("\nTransaction successful!");
59    }
60
61    // 5. Verify the final state of the database.
62    // The balances should be updated because the transaction succeeded.
63    println!("\nFinal state:");
64    println!("  - Alice's balance: {}", db.get("user:alice")?.unwrap());
65    println!("  - Bob's balance:   {}", db.get("user:bob")?.unwrap());
66
67    assert_eq!(db.get("user:alice")?.unwrap(), "80");
68    assert_eq!(db.get("user:bob")?.unwrap(), "70");
69
70    Ok(())
71}
Source

pub fn set( &self, key: &str, val: &str, ttl: Option<Duration>, ) -> Result<(), TransientError>

Sets a key-value pair with an optional Time-To-Live (TTL).

If the key already exists, its value and TTL will be updated. If ttl is None, the key will be persistent.

§Errors

This function can return an error if there’s an issue with the underlying

Examples found in repository?
examples/metadata.rs (line 8)
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6    let db = DB::new(Path::new("./my_database"))?;
7
8    db.set("user:2", "Bob", None)?;
9
10    // Increment the frequency counter
11    db.increment_frequency("user:2")?;
12
13    // Get the metadata for the key
14    if let Some(meta) = db.get_metadata("user:2")? {
15        println!("'user:2' has been accessed {} time(s)", meta.freq);
16        // "'user:2' has been accessed 1 time(s)"
17    }
18
19    Ok(())
20}
More examples
Hide additional examples
examples/basic_operations.rs (line 11)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7    // 1. Open the database. It will be created if it doesn't exist.
8    let db = DB::new(Path::new("./my_database"))?;
9
10    // 2. Set a value with a 10-second TTL.
11    db.set("user:1", "Alice", Some(Duration::from_secs(10)))?;
12
13    // 3. Get the value back.
14    if let Some(value) = db.get("user:1")? {
15        println!("Found value: {}", value); // "Found value: Alice"
16    }
17
18    // 4. Remove the data.
19    db.remove("user:1")?;
20
21    Ok(())
22}
examples/prometheus_track.rs (line 50)
41fn main() -> Result<(), Box<dyn std::error::Error>> {
42    thread::spawn(server_main);
43
44    // Let the thread build the app first
45    // and Let prometheus scrape once
46    sleep(Duration::new(15, 0));
47
48    let db = DB::new(Path::new("./databasetest")).unwrap();
49
50    db.set("H", "haha", None).unwrap();
51    db.set("HAHAHHAH", "Skib", None).unwrap();
52    db.set("HI", "h", None).unwrap();
53    db.set("Chronos", "Temporal", None).unwrap();
54    db.set("pop", "HAHAHAHH", Some(Duration::new(0, 100000)))
55        .unwrap();
56    for i in 0..1000 {
57        db.get("HI").unwrap();
58        db.set(&format!("{i}"), "h", None).unwrap();
59    }
60    db.backup_to(Path::new("./backup/")).unwrap();
61
62    Ok(())
63}
examples/concurrency.rs (line 8)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7    let db = Arc::new(DB::new("./my_database".as_ref())?);
8    db.set("concurrent_key", "initial_value", None)?;
9
10    let mut handles = vec![];
11    for _ in 0..10 {
12        let db_clone = Arc::clone(&db);
13        let handle = thread::spawn(move || {
14            for _ in 0..100 {
15                db_clone.increment_frequency("concurrent_key").unwrap();
16            }
17        });
18        handles.push(handle);
19    }
20
21    for handle in handles {
22        handle.join().unwrap();
23    }
24
25    let final_meta = db.get_metadata("concurrent_key")?.unwrap();
26    println!("Final frequency: {}", final_meta.freq); // "Final frequency: 1000"
27
28    Ok(())
29}
examples/ttl.rs (line 11)
7fn main() -> Result<(), Box<dyn std::error::Error>> {
8    let db = DB::new(Path::new("./my_database"))?;
9
10    // Set a key with a 2-second TTL
11    db.set("session:123", "user_token", Some(Duration::from_secs(2)))?;
12    println!("'session:123' is set.");
13
14    // The key exists initially
15    assert!(db.get("session:123")?.is_some());
16
17    // Wait for the TTL to expire
18    sleep(Duration::from_secs(3));
19
20    // The key should now be gone
21    assert!(db.get("session:123")?.is_none());
22    println!("'session:123' has expired.");
23
24    // You can also update a key to make it permanent
25    db.set(
26        "user:permanent",
27        "This will last forever",
28        Some(Duration::from_secs(1))
29    )?;
30    db.set("user:permanent", "This will last forever", None)?; // Remove the TTL
31
32    sleep(Duration::from_secs(2));
33    assert!(db.get("user:permanent")?.is_some());
34    println!("'user:permanent' is still here.");
35
36    Ok(())
37}
examples/transaction.rs (line 16)
8fn main() -> Result<(), Box<dyn Error>> {
9    // 1. Setup a temporary database for the example.
10    let temp_dir = tempdir()?;
11    let db = DB::new(temp_dir.path())?;
12
13    println!("Database created successfully.");
14
15    // 2. Set the initial state for two user accounts.
16    db.set("user:alice", "100", None)?;
17    db.set("user:bob", "50", None)?;
18
19    println!("Initial state:");
20    println!("  - Alice's balance: {}", db.get("user:alice")?.unwrap());
21    println!("  - Bob's balance:   {}", db.get("user:bob")?.unwrap());
22    println!("\nAttempting to transfer 20 from Alice to Bob...");
23
24    // 3. Run the atomic transfer inside a transaction.
25    let transaction_result = db.transaction(|tx| {
26        // Get the current balances.
27        let alice_balance_str = tx.get("user:alice")?.unwrap();
28        let bob_balance_str = tx.get("user:bob")?.unwrap();
29
30        let mut alice_balance: u64 = alice_balance_str.parse()?;
31        let mut bob_balance: u64 = bob_balance_str.parse()?;
32
33        let transfer_amount = 20;
34
35        // Check if the transfer is possible.
36        if alice_balance < transfer_amount {
37            // By returning an error, we abort the entire transaction.
38            // No changes will be saved.
39            return Err(Box::from("Alice has insufficient funds!"));
40        }
41
42        // Perform the transfer.
43        alice_balance -= transfer_amount;
44        bob_balance += transfer_amount;
45
46        // Save the new balances.
47        tx.set("user:alice", &alice_balance.to_string(), None)?;
48        tx.set("user:bob", &bob_balance.to_string(), None)?;
49
50        // Return Ok to commit the transaction.
51        Ok(())
52    });
53
54    // 4. Check if the transaction succeeded.
55    if let Err(e) = transaction_result {
56        println!("\nTransaction failed: {}", e);
57    } else {
58        println!("\nTransaction successful!");
59    }
60
61    // 5. Verify the final state of the database.
62    // The balances should be updated because the transaction succeeded.
63    println!("\nFinal state:");
64    println!("  - Alice's balance: {}", db.get("user:alice")?.unwrap());
65    println!("  - Bob's balance:   {}", db.get("user:bob")?.unwrap());
66
67    assert_eq!(db.get("user:alice")?.unwrap(), "80");
68    assert_eq!(db.get("user:bob")?.unwrap(), "70");
69
70    Ok(())
71}
Source

pub fn get(&self, key: &str) -> Result<Option<String>, TransientError>

Retrieves the value for a given key.

§Errors

Returns an error if the value cannot be retrieved from the database or if the value is not valid UTF-8.

Examples found in repository?
examples/basic_operations.rs (line 14)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7    // 1. Open the database. It will be created if it doesn't exist.
8    let db = DB::new(Path::new("./my_database"))?;
9
10    // 2. Set a value with a 10-second TTL.
11    db.set("user:1", "Alice", Some(Duration::from_secs(10)))?;
12
13    // 3. Get the value back.
14    if let Some(value) = db.get("user:1")? {
15        println!("Found value: {}", value); // "Found value: Alice"
16    }
17
18    // 4. Remove the data.
19    db.remove("user:1")?;
20
21    Ok(())
22}
More examples
Hide additional examples
examples/prometheus_track.rs (line 57)
41fn main() -> Result<(), Box<dyn std::error::Error>> {
42    thread::spawn(server_main);
43
44    // Let the thread build the app first
45    // and Let prometheus scrape once
46    sleep(Duration::new(15, 0));
47
48    let db = DB::new(Path::new("./databasetest")).unwrap();
49
50    db.set("H", "haha", None).unwrap();
51    db.set("HAHAHHAH", "Skib", None).unwrap();
52    db.set("HI", "h", None).unwrap();
53    db.set("Chronos", "Temporal", None).unwrap();
54    db.set("pop", "HAHAHAHH", Some(Duration::new(0, 100000)))
55        .unwrap();
56    for i in 0..1000 {
57        db.get("HI").unwrap();
58        db.set(&format!("{i}"), "h", None).unwrap();
59    }
60    db.backup_to(Path::new("./backup/")).unwrap();
61
62    Ok(())
63}
examples/ttl.rs (line 15)
7fn main() -> Result<(), Box<dyn std::error::Error>> {
8    let db = DB::new(Path::new("./my_database"))?;
9
10    // Set a key with a 2-second TTL
11    db.set("session:123", "user_token", Some(Duration::from_secs(2)))?;
12    println!("'session:123' is set.");
13
14    // The key exists initially
15    assert!(db.get("session:123")?.is_some());
16
17    // Wait for the TTL to expire
18    sleep(Duration::from_secs(3));
19
20    // The key should now be gone
21    assert!(db.get("session:123")?.is_none());
22    println!("'session:123' has expired.");
23
24    // You can also update a key to make it permanent
25    db.set(
26        "user:permanent",
27        "This will last forever",
28        Some(Duration::from_secs(1))
29    )?;
30    db.set("user:permanent", "This will last forever", None)?; // Remove the TTL
31
32    sleep(Duration::from_secs(2));
33    assert!(db.get("user:permanent")?.is_some());
34    println!("'user:permanent' is still here.");
35
36    Ok(())
37}
examples/transaction.rs (line 20)
8fn main() -> Result<(), Box<dyn Error>> {
9    // 1. Setup a temporary database for the example.
10    let temp_dir = tempdir()?;
11    let db = DB::new(temp_dir.path())?;
12
13    println!("Database created successfully.");
14
15    // 2. Set the initial state for two user accounts.
16    db.set("user:alice", "100", None)?;
17    db.set("user:bob", "50", None)?;
18
19    println!("Initial state:");
20    println!("  - Alice's balance: {}", db.get("user:alice")?.unwrap());
21    println!("  - Bob's balance:   {}", db.get("user:bob")?.unwrap());
22    println!("\nAttempting to transfer 20 from Alice to Bob...");
23
24    // 3. Run the atomic transfer inside a transaction.
25    let transaction_result = db.transaction(|tx| {
26        // Get the current balances.
27        let alice_balance_str = tx.get("user:alice")?.unwrap();
28        let bob_balance_str = tx.get("user:bob")?.unwrap();
29
30        let mut alice_balance: u64 = alice_balance_str.parse()?;
31        let mut bob_balance: u64 = bob_balance_str.parse()?;
32
33        let transfer_amount = 20;
34
35        // Check if the transfer is possible.
36        if alice_balance < transfer_amount {
37            // By returning an error, we abort the entire transaction.
38            // No changes will be saved.
39            return Err(Box::from("Alice has insufficient funds!"));
40        }
41
42        // Perform the transfer.
43        alice_balance -= transfer_amount;
44        bob_balance += transfer_amount;
45
46        // Save the new balances.
47        tx.set("user:alice", &alice_balance.to_string(), None)?;
48        tx.set("user:bob", &bob_balance.to_string(), None)?;
49
50        // Return Ok to commit the transaction.
51        Ok(())
52    });
53
54    // 4. Check if the transaction succeeded.
55    if let Err(e) = transaction_result {
56        println!("\nTransaction failed: {}", e);
57    } else {
58        println!("\nTransaction successful!");
59    }
60
61    // 5. Verify the final state of the database.
62    // The balances should be updated because the transaction succeeded.
63    println!("\nFinal state:");
64    println!("  - Alice's balance: {}", db.get("user:alice")?.unwrap());
65    println!("  - Bob's balance:   {}", db.get("user:bob")?.unwrap());
66
67    assert_eq!(db.get("user:alice")?.unwrap(), "80");
68    assert_eq!(db.get("user:bob")?.unwrap(), "70");
69
70    Ok(())
71}
Source

pub fn increment_frequency(&self, key: &str) -> Result<(), TransientError>

Atomically increments the frequency counter for a given key.

§Errors

This function can return an error if the key does not exist or if there is an issue with the compare-and-swap operation.

Examples found in repository?
examples/metadata.rs (line 11)
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6    let db = DB::new(Path::new("./my_database"))?;
7
8    db.set("user:2", "Bob", None)?;
9
10    // Increment the frequency counter
11    db.increment_frequency("user:2")?;
12
13    // Get the metadata for the key
14    if let Some(meta) = db.get_metadata("user:2")? {
15        println!("'user:2' has been accessed {} time(s)", meta.freq);
16        // "'user:2' has been accessed 1 time(s)"
17    }
18
19    Ok(())
20}
More examples
Hide additional examples
examples/concurrency.rs (line 15)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7    let db = Arc::new(DB::new("./my_database".as_ref())?);
8    db.set("concurrent_key", "initial_value", None)?;
9
10    let mut handles = vec![];
11    for _ in 0..10 {
12        let db_clone = Arc::clone(&db);
13        let handle = thread::spawn(move || {
14            for _ in 0..100 {
15                db_clone.increment_frequency("concurrent_key").unwrap();
16            }
17        });
18        handles.push(handle);
19    }
20
21    for handle in handles {
22        handle.join().unwrap();
23    }
24
25    let final_meta = db.get_metadata("concurrent_key")?.unwrap();
26    println!("Final frequency: {}", final_meta.freq); // "Final frequency: 1000"
27
28    Ok(())
29}
Source

pub fn remove(&self, key: &str) -> Result<(), TransientError>

Removes a key-value pair and its associated metadata from the database.

§Errors

Can return an error if the transaction to remove the data fails.

Examples found in repository?
examples/basic_operations.rs (line 19)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7    // 1. Open the database. It will be created if it doesn't exist.
8    let db = DB::new(Path::new("./my_database"))?;
9
10    // 2. Set a value with a 10-second TTL.
11    db.set("user:1", "Alice", Some(Duration::from_secs(10)))?;
12
13    // 3. Get the value back.
14    if let Some(value) = db.get("user:1")? {
15        println!("Found value: {}", value); // "Found value: Alice"
16    }
17
18    // 4. Remove the data.
19    db.remove("user:1")?;
20
21    Ok(())
22}
Source

pub fn get_metadata( &self, key: &str, ) -> Result<Option<Metadata>, TransientError>

Retrieves the metadata for a given key.

§Errors

Returns an error if the metadata cannot be retrieved or deserialized.

Examples found in repository?
examples/metadata.rs (line 14)
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6    let db = DB::new(Path::new("./my_database"))?;
7
8    db.set("user:2", "Bob", None)?;
9
10    // Increment the frequency counter
11    db.increment_frequency("user:2")?;
12
13    // Get the metadata for the key
14    if let Some(meta) = db.get_metadata("user:2")? {
15        println!("'user:2' has been accessed {} time(s)", meta.freq);
16        // "'user:2' has been accessed 1 time(s)"
17    }
18
19    Ok(())
20}
More examples
Hide additional examples
examples/concurrency.rs (line 25)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7    let db = Arc::new(DB::new("./my_database".as_ref())?);
8    db.set("concurrent_key", "initial_value", None)?;
9
10    let mut handles = vec![];
11    for _ in 0..10 {
12        let db_clone = Arc::clone(&db);
13        let handle = thread::spawn(move || {
14            for _ in 0..100 {
15                db_clone.increment_frequency("concurrent_key").unwrap();
16            }
17        });
18        handles.push(handle);
19    }
20
21    for handle in handles {
22        handle.join().unwrap();
23    }
24
25    let final_meta = db.get_metadata("concurrent_key")?.unwrap();
26    println!("Final frequency: {}", final_meta.freq); // "Final frequency: 1000"
27
28    Ok(())
29}
Source

pub fn flush(&self) -> Result<(), TransientError>

Flushes all the trees in the database.

§Errors

Returns an error if sled fails to flush the trees.

Source

pub fn backup_to(&self, path: &Path) -> Result<(), TransientError>

Backup the database to the corresponding path.

§Errors

This function returns an Error if the following occurs:

  • Any corresponding folder in the path is not found
  • Zip or sled fails because of any reason
  • IOError when the file is being access by the OS for something else
  • Failing to parse any data to a u8
Examples found in repository?
examples/prometheus_track.rs (line 60)
41fn main() -> Result<(), Box<dyn std::error::Error>> {
42    thread::spawn(server_main);
43
44    // Let the thread build the app first
45    // and Let prometheus scrape once
46    sleep(Duration::new(15, 0));
47
48    let db = DB::new(Path::new("./databasetest")).unwrap();
49
50    db.set("H", "haha", None).unwrap();
51    db.set("HAHAHHAH", "Skib", None).unwrap();
52    db.set("HI", "h", None).unwrap();
53    db.set("Chronos", "Temporal", None).unwrap();
54    db.set("pop", "HAHAHAHH", Some(Duration::new(0, 100000)))
55        .unwrap();
56    for i in 0..1000 {
57        db.get("HI").unwrap();
58        db.set(&format!("{i}"), "h", None).unwrap();
59    }
60    db.backup_to(Path::new("./backup/")).unwrap();
61
62    Ok(())
63}
Source

pub fn load_from(path: &Path, db_path: &Path) -> Result<DB, TransientError>

This function loads the backup archive from the path given and loads the database in the db_path

§Errors

This Function will fail if the following happens:

  • Any corresponding folder in the path is not found
  • Zip or sled fails because of any reason
  • IOError when the file is being access by the OS for something else
  • It fails to parse the .epoch file which may occur due to data corruption or wrong formatting.

Trait Implementations§

Source§

impl Debug for DB

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Drop for DB

Source§

fn drop(&mut self)

Gracefully shuts down the TTL background thread when the DB instance goes out of scope.

Auto Trait Implementations§

§

impl Freeze for DB

§

impl !RefUnwindSafe for DB

§

impl Send for DB

§

impl Sync for DB

§

impl Unpin for DB

§

impl !UnwindSafe for DB

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.