Struct DB

Source
pub struct DB { /* 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

Implementations§

Source§

impl DB

Source

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

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 5)
4fn main() -> Result<(), Box<dyn std::error::Error>> {
5    let db = DB::new(Path::new("./my_database"))?;
6
7    db.set("user:2", "Bob", None)?;
8
9    // Increment the frequency counter
10    db.increment_frequency("user:2")?;
11
12    // Get the metadata for the key
13    if let Some(meta) = db.get_metadata("user:2")? {
14        println!("'user:2' has been accessed {} time(s)", meta.freq);
15        // "'user:2' has been accessed 1 time(s)"
16    }
17
18    Ok(())
19}
More examples
Hide additional examples
examples/basic_operations.rs (line 7)
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6    // 1. Open the database. It will be created if it doesn't exist.
7    let db = DB::new(Path::new("./my_database"))?;
8
9    // 2. Set a value with a 10-second TTL.
10    db.set("user:1", "Alice", Some(Duration::from_secs(10)))?;
11
12    // 3. Get the value back.
13    if let Some(value) = db.get("user:1")? {
14        println!("Found value: {}", value); // "Found value: Alice"
15    }
16
17    // 4. Remove the data.
18    db.remove("user:1")?;
19
20    Ok(())
21}
examples/concurrency.rs (line 6)
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6    let db = Arc::new(DB::new("./my_database".as_ref())?);
7    db.set("concurrent_key", "initial_value", None)?;
8
9    let mut handles = vec![];
10    for _ in 0..10 {
11        let db_clone = Arc::clone(&db);
12        let handle = thread::spawn(move || {
13            for _ in 0..100 {
14                db_clone.increment_frequency("concurrent_key").unwrap();
15            }
16        });
17        handles.push(handle);
18    }
19
20    for handle in handles {
21        handle.join().unwrap();
22    }
23
24    let final_meta = db.get_metadata("concurrent_key")?.unwrap();
25    println!("Final frequency: {}", final_meta.freq); // "Final frequency: 1000"
26
27    Ok(())
28}
examples/ttl.rs (line 7)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7    let db = DB::new(Path::new("./my_database"))?;
8
9    // Set a key with a 2-second TTL
10    db.set("session:123", "user_token", Some(Duration::from_secs(2)))?;
11    println!("'session:123' is set.");
12
13    // The key exists initially
14    assert!(db.get("session:123")?.is_some());
15
16    // Wait for the TTL to expire
17    sleep(Duration::from_secs(3));
18
19    // The key should now be gone
20    assert!(db.get("session:123")?.is_none());
21    println!("'session:123' has expired.");
22
23    // You can also update a key to make it permanent
24    db.set(
25        "user:permanent",
26        "This will last forever",
27        Some(Duration::from_secs(1)),
28    )?;
29    db.set("user:permanent", "This will last forever", None)?; // Remove the TTL
30
31    sleep(Duration::from_secs(2));
32    assert!(db.get("user:permanent")?.is_some());
33    println!("'user:permanent' is still here.");
34
35    Ok(())
36}
Source

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

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 7)
4fn main() -> Result<(), Box<dyn std::error::Error>> {
5    let db = DB::new(Path::new("./my_database"))?;
6
7    db.set("user:2", "Bob", None)?;
8
9    // Increment the frequency counter
10    db.increment_frequency("user:2")?;
11
12    // Get the metadata for the key
13    if let Some(meta) = db.get_metadata("user:2")? {
14        println!("'user:2' has been accessed {} time(s)", meta.freq);
15        // "'user:2' has been accessed 1 time(s)"
16    }
17
18    Ok(())
19}
More examples
Hide additional examples
examples/basic_operations.rs (line 10)
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6    // 1. Open the database. It will be created if it doesn't exist.
7    let db = DB::new(Path::new("./my_database"))?;
8
9    // 2. Set a value with a 10-second TTL.
10    db.set("user:1", "Alice", Some(Duration::from_secs(10)))?;
11
12    // 3. Get the value back.
13    if let Some(value) = db.get("user:1")? {
14        println!("Found value: {}", value); // "Found value: Alice"
15    }
16
17    // 4. Remove the data.
18    db.remove("user:1")?;
19
20    Ok(())
21}
examples/concurrency.rs (line 7)
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6    let db = Arc::new(DB::new("./my_database".as_ref())?);
7    db.set("concurrent_key", "initial_value", None)?;
8
9    let mut handles = vec![];
10    for _ in 0..10 {
11        let db_clone = Arc::clone(&db);
12        let handle = thread::spawn(move || {
13            for _ in 0..100 {
14                db_clone.increment_frequency("concurrent_key").unwrap();
15            }
16        });
17        handles.push(handle);
18    }
19
20    for handle in handles {
21        handle.join().unwrap();
22    }
23
24    let final_meta = db.get_metadata("concurrent_key")?.unwrap();
25    println!("Final frequency: {}", final_meta.freq); // "Final frequency: 1000"
26
27    Ok(())
28}
examples/ttl.rs (line 10)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7    let db = DB::new(Path::new("./my_database"))?;
8
9    // Set a key with a 2-second TTL
10    db.set("session:123", "user_token", Some(Duration::from_secs(2)))?;
11    println!("'session:123' is set.");
12
13    // The key exists initially
14    assert!(db.get("session:123")?.is_some());
15
16    // Wait for the TTL to expire
17    sleep(Duration::from_secs(3));
18
19    // The key should now be gone
20    assert!(db.get("session:123")?.is_none());
21    println!("'session:123' has expired.");
22
23    // You can also update a key to make it permanent
24    db.set(
25        "user:permanent",
26        "This will last forever",
27        Some(Duration::from_secs(1)),
28    )?;
29    db.set("user:permanent", "This will last forever", None)?; // Remove the TTL
30
31    sleep(Duration::from_secs(2));
32    assert!(db.get("user:permanent")?.is_some());
33    println!("'user:permanent' is still here.");
34
35    Ok(())
36}
Source

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

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 13)
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6    // 1. Open the database. It will be created if it doesn't exist.
7    let db = DB::new(Path::new("./my_database"))?;
8
9    // 2. Set a value with a 10-second TTL.
10    db.set("user:1", "Alice", Some(Duration::from_secs(10)))?;
11
12    // 3. Get the value back.
13    if let Some(value) = db.get("user:1")? {
14        println!("Found value: {}", value); // "Found value: Alice"
15    }
16
17    // 4. Remove the data.
18    db.remove("user:1")?;
19
20    Ok(())
21}
More examples
Hide additional examples
examples/ttl.rs (line 14)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7    let db = DB::new(Path::new("./my_database"))?;
8
9    // Set a key with a 2-second TTL
10    db.set("session:123", "user_token", Some(Duration::from_secs(2)))?;
11    println!("'session:123' is set.");
12
13    // The key exists initially
14    assert!(db.get("session:123")?.is_some());
15
16    // Wait for the TTL to expire
17    sleep(Duration::from_secs(3));
18
19    // The key should now be gone
20    assert!(db.get("session:123")?.is_none());
21    println!("'session:123' has expired.");
22
23    // You can also update a key to make it permanent
24    db.set(
25        "user:permanent",
26        "This will last forever",
27        Some(Duration::from_secs(1)),
28    )?;
29    db.set("user:permanent", "This will last forever", None)?; // Remove the TTL
30
31    sleep(Duration::from_secs(2));
32    assert!(db.get("user:permanent")?.is_some());
33    println!("'user:permanent' is still here.");
34
35    Ok(())
36}
Source

pub fn increment_frequency(&self, key: &str) -> Result<(), Box<dyn Error>>

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

pub fn remove(&self, key: &str) -> Result<(), Box<dyn Error>>

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

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

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

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, 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.