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
impl DB
Sourcepub fn transaction<F>(&self, f: F) -> Result<(), TransientError>
pub fn transaction<F>(&self, f: F) -> Result<(), TransientError>
Examples found in repository?
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
impl DB
Sourcepub fn new(path: &Path) -> Result<DB, TransientError>
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?
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
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}
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}
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}
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}
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}
Sourcepub fn set(
&self,
key: &str,
val: &str,
ttl: Option<Duration>,
) -> Result<(), TransientError>
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?
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
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}
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}
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}
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}
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}
Sourcepub fn get(&self, key: &str) -> Result<Option<String>, TransientError>
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?
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
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}
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}
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}
Sourcepub fn increment_frequency(&self, key: &str) -> Result<(), TransientError>
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?
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
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}
Sourcepub fn remove(&self, key: &str) -> Result<(), TransientError>
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?
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}
Sourcepub fn get_metadata(
&self,
key: &str,
) -> Result<Option<Metadata>, TransientError>
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?
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
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}
Sourcepub fn flush(&self) -> Result<(), TransientError>
pub fn flush(&self) -> Result<(), TransientError>
Sourcepub fn backup_to(&self, path: &Path) -> Result<(), TransientError>
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?
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}
Sourcepub fn load_from(path: &Path, db_path: &Path) -> Result<DB, TransientError>
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.