1
use std::time::Duration;
2

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

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

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

            
18
    // The set_key method can be awaited to insert/replace a key. Values can be
19
    // anything supported by Serde.
20
1
    db.set_key("mykey", &1_u32).await?;
21

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

            
30
    // Retrieving is simple too.
31
1
    let value = db.get_key("mykey").into().await?;
32
1
    assert_eq!(value, Some(2_u32));
33

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

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

            
47
1
    let second_try = db
48
1
        .set_key("lockname", &())
49
1
        .only_if_vacant()
50
1
        .expire_in(Duration::from_millis(100))
51
1
        .await?;
52
1
    assert_eq!(second_try, KeyStatus::NotChanged);
53

            
54
1
    Ok(())
55
}
56

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