spin_sdk/key_value.rs
1//! Spin key-value persistent storage
2//!
3//! This module provides a generic interface for key-value storage, which may be implemented by the host various
4//! ways (e.g. via an in-memory table, a local file, or a remote database). Details such as consistency model and
5//! durability will depend on the implementation and may vary from one to store to the next.
6//!
7//! # Examples
8//!
9//! Open the default store and set the 'message' key:
10//!
11//! ```no_run
12//! # fn main() -> anyhow::Result<()> {
13//! let store = spin_sdk::key_value::Store::open_default()?;
14//! store.set("message", "Hello world".as_bytes())?;
15//! # Ok(())
16//! # }
17//! ```
18
19use super::wit::v2::key_value;
20
21#[cfg(feature = "json")]
22use serde::{de::DeserializeOwned, Serialize};
23
24#[doc(inline)]
25pub use key_value::Error;
26
27/// An open key-value store.
28///
29/// # Examples
30///
31/// Open the default store and set the 'message' key:
32///
33/// ```no_run
34/// # fn main() -> anyhow::Result<()> {
35/// let store = spin_sdk::key_value::Store::open_default()?;
36/// store.set("message", "Hello world".as_bytes())?;
37/// # Ok(())
38/// # }
39/// ```
40///
41/// Open the default store and get the 'message' key:
42///
43/// ```no_run
44/// # fn main() -> anyhow::Result<()> {
45/// let store = spin_sdk::key_value::Store::open_default()?;
46/// let message = store.get("message")?;
47/// let response = message.unwrap_or_else(|| "not found".into());
48/// # Ok(())
49/// # }
50/// ```
51///
52/// Open a named store and list all the keys defined in it:
53///
54/// ```no_run
55/// # fn main() -> anyhow::Result<()> {
56/// let store = spin_sdk::key_value::Store::open("finance")?;
57/// let keys = store.get_keys()?;
58/// # Ok(())
59/// # }
60/// ```
61///
62/// Open the default store and delete the 'message' key:
63///
64/// ```no_run
65/// # fn main() -> anyhow::Result<()> {
66/// let store = spin_sdk::key_value::Store::open_default()?;
67/// store.delete("message")?;
68/// # Ok(())
69/// # }
70/// ```
71#[doc(inline)]
72pub use key_value::Store;
73
74impl Store {
75 /// Open the default store.
76 ///
77 /// This is equivalent to `Store::open("default")`.
78 pub fn open_default() -> Result<Self, Error> {
79 Self::open("default")
80 }
81}
82
83impl Store {
84 #[cfg(feature = "json")]
85 /// Serialize the given data to JSON, then set it as the value for the specified `key`.
86 ///
87 /// # Examples
88 ///
89 /// Open the default store and save a customer information document against the customer ID:
90 ///
91 /// ```no_run
92 /// # use serde::{Deserialize, Serialize};
93 /// #[derive(Deserialize, Serialize)]
94 /// struct Customer {
95 /// name: String,
96 /// address: Vec<String>,
97 /// }
98 ///
99 /// # fn main() -> anyhow::Result<()> {
100 /// let customer_id = "CR1234567";
101 /// let customer = Customer {
102 /// name: "Alice".to_owned(),
103 /// address: vec!["Wonderland Way".to_owned()],
104 /// };
105 ///
106 /// let store = spin_sdk::key_value::Store::open_default()?;
107 /// store.set_json(customer_id, &customer)?;
108 /// # Ok(())
109 /// # }
110 /// ```
111 pub fn set_json<T: Serialize>(
112 &self,
113 key: impl AsRef<str>,
114 value: &T,
115 ) -> Result<(), anyhow::Error> {
116 Ok(self.set(key.as_ref(), &serde_json::to_vec(value)?)?)
117 }
118
119 #[cfg(feature = "json")]
120 /// Deserialize an instance of type `T` from the value of `key`.
121 ///
122 /// # Examples
123 ///
124 /// Open the default store and retrieve a customer information document by customer ID:
125 ///
126 /// ```no_run
127 /// # use serde::{Deserialize, Serialize};
128 /// #[derive(Deserialize, Serialize)]
129 /// struct Customer {
130 /// name: String,
131 /// address: Vec<String>,
132 /// }
133 ///
134 /// # fn main() -> anyhow::Result<()> {
135 /// let customer_id = "CR1234567";
136 ///
137 /// let store = spin_sdk::key_value::Store::open_default()?;
138 /// let customer = store.get_json::<Customer>(customer_id)?;
139 /// # Ok(())
140 /// # }
141 /// ```
142 pub fn get_json<T: DeserializeOwned>(
143 &self,
144 key: impl AsRef<str>,
145 ) -> Result<Option<T>, anyhow::Error> {
146 let Some(value) = self.get(key.as_ref())? else {
147 return Ok(None);
148 };
149 Ok(serde_json::from_slice(&value)?)
150 }
151}