1
1
use std::time::Duration;
2

            
3
use bonsaidb::{
4
    core::keyvalue::{AsyncKeyValue, KeyStatus},
5
    local::{
6
        config::{Builder, StorageConfiguration},
7
        AsyncDatabase,
8
    },
9
};
10

            
11
// BonsaiDb supports a lightweight, atomic key-value store in addition to its
12
// acid-compliant transactional storage. This interface is meant to replicate
13
// functionality that you might use something like Redis for -- lightweight
14
// caching, or fast atomic operations. As with all of BonsaiDb's core features,
15
// the Key-Value store is supported across all methods of accessing BonsaiDb.
16

            
17
#[tokio::main]
18
1
async fn main() -> Result<(), bonsaidb::core::Error> {
19
1
    let db =
20
1
        AsyncDatabase::open::<()>(StorageConfiguration::new("key-value-store.bonsaidb")).await?;
21

            
22
    // The set_key method can be awaited to insert/replace a key. Values can be
23
    // anything supported by Serde.
24
1
    db.set_key("mykey", &1_u32).await?;
25

            
26
    // Or, you can customize it's behavior:
27
1
    let old_value = db
28
1
        .set_key("mykey", &2_u32)
29
1
        .only_if_exists()
30
1
        .returning_previous_as()
31
1
        .await?;
32
1
    assert_eq!(old_value, Some(1_u32));
33

            
34
    // Retrieving is simple too.
35
1
    let value = db.get_key("mykey").into().await?;
36
1
    assert_eq!(value, Some(2_u32));
37

            
38
    // Namespacing is built-in as well, so that you can easily separate storage.
39
1
    let value = db.with_key_namespace("anamespace").get_key("mykey").await?;
40
1
    assert!(value.is_none());
41

            
42
    // Because of the atomic nature of the key-value store, you can use set_key
43
    // as a synchronized lock:
44
1
    let result = db
45
1
        .set_key("lockname", &()) // A useful value would be the unique id of the worker that aquired the lock.
46
1
        .only_if_vacant()
47
1
        .expire_in(Duration::from_millis(100))
48
1
        .await?;
49
1
    assert_eq!(result, KeyStatus::Inserted);
50

            
51
1
    let second_try = db
52
1
        .set_key("lockname", &())
53
1
        .only_if_vacant()
54
1
        .expire_in(Duration::from_millis(100))
55
1
        .await?;
56
1
    assert_eq!(second_try, KeyStatus::NotChanged);
57

            
58
1
    Ok(())
59
1
}
60

            
61
1
#[test]
62
1
fn runs() {
63
1
    let path = std::path::Path::new("key-value-store.bonsaidb");
64
1
    if path.exists() {
65
1
        std::fs::remove_dir_all(path).unwrap();
66
1
    }
67
1
    main().unwrap()
68
1
}