Skip to content

Commit ef78f0e

Browse files
authored
Merge pull request #128 from kinode-dao/bp/kvdocs
kv: more docstrings
2 parents ea8490a + 3485a06 commit ef78f0e

File tree

1 file changed

+158
-0
lines changed

1 file changed

+158
-0
lines changed

src/kv.rs

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::{get_blob, Message, PackageId, Request};
2+
use alloy::rpc::types::error;
23
use serde::{de::DeserializeOwned, Deserialize, Serialize};
34
use std::marker::PhantomData;
45
use thiserror::Error;
@@ -13,40 +14,98 @@ pub struct KvRequest {
1314
pub action: KvAction,
1415
}
1516

17+
/// IPC Action format, representing operations that can be performed on the key-value runtime module.
18+
/// These actions are included in a KvRequest sent to the kv:distro:sys runtime module.
1619
#[derive(Debug, Serialize, Deserialize, Clone)]
1720
pub enum KvAction {
21+
/// Opens an existing key-value database or creates a new one if it doesn't exist.
1822
Open,
23+
/// Permanently deletes the entire key-value database.
1924
RemoveDb,
25+
/// Sets a value for the specified key in the database.
26+
///
27+
/// # Parameters
28+
/// * `key` - The key as a byte vector
29+
/// * `tx_id` - Optional transaction ID if this operation is part of a transaction
2030
Set { key: Vec<u8>, tx_id: Option<u64> },
31+
/// Deletes a key-value pair from the database.
32+
///
33+
/// # Parameters
34+
/// * `key` - The key to delete as a byte vector
35+
/// * `tx_id` - Optional transaction ID if this operation is part of a transaction
2136
Delete { key: Vec<u8>, tx_id: Option<u64> },
37+
/// Retrieves the value associated with the specified key.
38+
///
39+
/// # Parameters
40+
/// * `key` - The key to look up as a byte vector
2241
Get { key: Vec<u8> },
42+
/// Begins a new transaction for atomic operations.
2343
BeginTx,
44+
/// Commits all operations in the specified transaction.
45+
///
46+
/// # Parameters
47+
/// * `tx_id` - The ID of the transaction to commit
2448
Commit { tx_id: u64 },
49+
/// Creates a backup of the database.
2550
Backup,
2651
}
2752

53+
/// Response types for key-value store operations.
54+
/// These responses are returned after processing a KvAction request.
2855
#[derive(Debug, Serialize, Deserialize)]
2956
pub enum KvResponse {
57+
/// Indicates successful completion of an operation.
3058
Ok,
59+
/// Returns the transaction ID for a newly created transaction.
60+
///
61+
/// # Fields
62+
/// * `tx_id` - The ID of the newly created transaction
3163
BeginTx { tx_id: u64 },
64+
/// Returns the key that was retrieved from the database.
65+
///
66+
/// # Fields
67+
/// * `key` - The retrieved key as a byte vector
3268
Get { key: Vec<u8> },
69+
/// Indicates an error occurred during the operation.
3370
Err(KvError),
3471
}
3572

73+
/// Errors that can occur during key-value store operations.
74+
/// These errors are returned as part of `KvResponse::Err` when an operation fails.
3675
#[derive(Debug, Serialize, Deserialize, Error)]
3776
pub enum KvError {
77+
/// The requested database does not exist.
3878
#[error("kv: DbDoesNotExist")]
3979
NoDb,
80+
/// The requested key was not found in the database.
4081
#[error("kv: KeyNotFound")]
4182
KeyNotFound,
83+
/// No active transaction found for the given transaction ID.
4284
#[error("kv: no Tx found")]
4385
NoTx,
86+
/// The operation requires capabilities that the caller doesn't have.
87+
///
88+
/// # Fields
89+
/// * `error` - Description of the missing capability or permission
4490
#[error("kv: No capability: {error}")]
4591
NoCap { error: String },
92+
/// An internal RocksDB error occurred during the operation.
93+
///
94+
/// # Fields
95+
/// * `action` - The operation that was being performed
96+
/// * `error` - The specific error message from RocksDB
4697
#[error("kv: rocksdb internal error: {error}")]
4798
RocksDBError { action: String, error: String },
99+
/// Error parsing or processing input data.
100+
///
101+
/// # Fields
102+
/// * `error` - Description of what was invalid about the input
48103
#[error("kv: input bytes/json/key error: {error}")]
49104
InputError { error: String },
105+
/// An I/O error occurred during the operation.
106+
///
107+
/// # Fields
108+
/// * `error` - Description of the I/O error
50109
#[error("kv: IO error: {error}")]
51110
IOError { error: String },
52111
}
@@ -306,6 +365,105 @@ where
306365
}
307366
}
308367

368+
impl Kv<Vec<u8>, Vec<u8>> {
369+
/// Get raw bytes directly
370+
pub fn get_raw(&self, key: &[u8]) -> anyhow::Result<Vec<u8>> {
371+
let res = Request::new()
372+
.target(("our", "kv", "distro", "sys"))
373+
.body(serde_json::to_vec(&KvRequest {
374+
package_id: self.package_id.clone(),
375+
db: self.db.clone(),
376+
action: KvAction::Get { key: key.to_vec() },
377+
})?)
378+
.send_and_await_response(self.timeout)?;
379+
380+
match res {
381+
Ok(Message::Response { body, .. }) => {
382+
let response = serde_json::from_slice::<KvResponse>(&body)?;
383+
384+
match response {
385+
KvResponse::Get { .. } => {
386+
let bytes = match get_blob() {
387+
Some(bytes) => bytes.bytes,
388+
None => return Err(anyhow::anyhow!("kv: no blob")),
389+
};
390+
Ok(bytes)
391+
}
392+
KvResponse::Err { 0: error } => Err(error.into()),
393+
_ => Err(anyhow::anyhow!("kv: unexpected response {:?}", response)),
394+
}
395+
}
396+
_ => Err(anyhow::anyhow!("kv: unexpected message: {:?}", res)),
397+
}
398+
}
399+
400+
/// Set raw bytes directly
401+
pub fn set_raw(&self, key: &[u8], value: &[u8], tx_id: Option<u64>) -> anyhow::Result<()> {
402+
let res = Request::new()
403+
.target(("our", "kv", "distro", "sys"))
404+
.body(serde_json::to_vec(&KvRequest {
405+
package_id: self.package_id.clone(),
406+
db: self.db.clone(),
407+
action: KvAction::Set {
408+
key: key.to_vec(),
409+
tx_id,
410+
},
411+
})?)
412+
.blob_bytes(value.to_vec())
413+
.send_and_await_response(self.timeout)?;
414+
415+
match res {
416+
Ok(Message::Response { body, .. }) => {
417+
let response = serde_json::from_slice::<KvResponse>(&body)?;
418+
419+
match response {
420+
KvResponse::Ok => Ok(()),
421+
KvResponse::Err { 0: error } => Err(error.into()),
422+
_ => Err(anyhow::anyhow!("kv: unexpected response {:?}", response)),
423+
}
424+
}
425+
_ => Err(anyhow::anyhow!("kv: unexpected message: {:?}", res)),
426+
}
427+
}
428+
429+
/// Delete raw bytes directly
430+
pub fn delete_raw(&self, key: &[u8], tx_id: Option<u64>) -> anyhow::Result<()> {
431+
let res = Request::new()
432+
.target(("our", "kv", "distro", "sys"))
433+
.body(serde_json::to_vec(&KvRequest {
434+
package_id: self.package_id.clone(),
435+
db: self.db.clone(),
436+
action: KvAction::Delete {
437+
key: key.to_vec(),
438+
tx_id,
439+
},
440+
})?)
441+
.send_and_await_response(self.timeout)?;
442+
443+
match res {
444+
Ok(Message::Response { body, .. }) => {
445+
let response = serde_json::from_slice::<KvResponse>(&body)?;
446+
447+
match response {
448+
KvResponse::Ok => Ok(()),
449+
KvResponse::Err { 0: error } => Err(error.into()),
450+
_ => Err(anyhow::anyhow!("kv: unexpected response {:?}", response)),
451+
}
452+
}
453+
_ => Err(anyhow::anyhow!("kv: unexpected message: {:?}", res)),
454+
}
455+
}
456+
}
457+
458+
/// Helper function to open a raw bytes key-value store
459+
pub fn open_raw(
460+
package_id: PackageId,
461+
db: &str,
462+
timeout: Option<u64>,
463+
) -> anyhow::Result<Kv<Vec<u8>, Vec<u8>>> {
464+
open(package_id, db, timeout)
465+
}
466+
309467
/// Opens or creates a kv db.
310468
pub fn open<K, V>(package_id: PackageId, db: &str, timeout: Option<u64>) -> anyhow::Result<Kv<K, V>>
311469
where

0 commit comments

Comments
 (0)