Skip to content

Commit 14c8087

Browse files
authored
Merge pull request #7 from AIBlockOfficial/restructure_data_entry
Restructure data entry for all routes
2 parents fab2aac + 150089d commit 14c8087

File tree

5 files changed

+138
-41
lines changed

5 files changed

+138
-41
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "valence_core"
3-
version = "0.1.5"
3+
version = "0.1.6"
44
edition = "2021"
55
license = "MIT"
66
keywords = ["blockchain", "L2", "peer-to-peer", "P2P"]

src/api/utils.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub fn get_cors() -> warp::cors::Builder {
4747
}
4848

4949
/// Easy and simple DELETE CORS
50-
pub fn delete_cors() -> warp::cors::Builder {
50+
pub fn del_cors() -> warp::cors::Builder {
5151
cors_builder(vec!["DELETE", "OPTIONS"])
5252
}
5353

src/db/handler.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use async_trait::async_trait;
22
use serde::{de::DeserializeOwned, Serialize};
3+
use std::collections::HashMap;
34

45
/// Trait for a key-value data store connection
56
#[async_trait]
@@ -18,10 +19,12 @@ pub trait KvStoreConnection {
1819
/// ### Arguments
1920
///
2021
/// * `key` - Key of the data entry to set
22+
/// * `value_id` - ID of the value to set
2123
/// * `value` - Value of the data entry to set
2224
async fn set_data<T: Serialize + Send + DeserializeOwned>(
2325
&mut self,
2426
key: &str,
27+
value_id: &str,
2528
value: T,
2629
) -> Result<(), Box<dyn std::error::Error + Send + Sync>>;
2730

@@ -30,11 +33,13 @@ pub trait KvStoreConnection {
3033
/// ### Arguments
3134
///
3235
/// * `key` - Key of the data entry to set
36+
/// * `value_id` - ID of the value to set
3337
/// * `value` - Value of the data entry to set
3438
/// * `seconds` - Number of seconds to expire the data entry in
3539
async fn set_data_with_expiry<T: Serialize + DeserializeOwned + Send>(
3640
&mut self,
3741
key: &str,
42+
value_id: &str,
3843
value: T,
3944
seconds: usize,
4045
) -> Result<(), Box<dyn std::error::Error + Send + Sync>>;
@@ -44,20 +49,24 @@ pub trait KvStoreConnection {
4449
/// ### Arguments
4550
///
4651
/// * `key` - Key of the data entry to delete
47-
async fn delete_data(
52+
/// * `value_id` - ID of the value to delete. If not provided, all values for the key are deleted
53+
async fn del_data(
4854
&mut self,
4955
key: &str,
56+
value_id: Option<&str>,
5057
) -> Result<(), Box<dyn std::error::Error + Send + Sync>>;
5158

5259
/// Gets a data entry from the cache
5360
///
5461
/// ### Arguments
5562
///
5663
/// * `key` - Key of the data entry to get
57-
async fn get_data<T: DeserializeOwned>(
64+
/// * `value_id` - ID of the value to get. If not provided, all values for the key are retrieved
65+
async fn get_data<T: Clone + DeserializeOwned>(
5866
&mut self,
5967
key: &str,
60-
) -> Result<Option<Vec<T>>, Box<dyn std::error::Error + Send + Sync>>;
68+
value_id: Option<&str>,
69+
) -> Result<Option<HashMap<String, T>>, Box<dyn std::error::Error + Send + Sync>>;
6170
}
6271

6372
#[async_trait]

src/db/mongo_db.rs

+71-22
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use async_trait::async_trait;
22
use mongodb::bson::{doc, DateTime, Document};
33
use mongodb::{options::ClientOptions, Client};
44
use serde::{de::DeserializeOwned, Serialize};
5+
use std::collections::HashMap;
56
use tracing::{event, span, trace, warn, Level};
67

78
use super::handler::KvStoreConnection;
@@ -75,6 +76,7 @@ impl KvStoreConnection for MongoDbConn {
7576
async fn set_data<T: Serialize + std::marker::Send + DeserializeOwned>(
7677
&mut self,
7778
key: &str,
79+
value_id: &str,
7880
value: T,
7981
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
8082
// Tracing
@@ -90,22 +92,22 @@ impl KvStoreConnection for MongoDbConn {
9092
let filter = doc! { "_id": key };
9193
let existing_doc = collection.find_one(filter.clone(), None).await?;
9294

93-
let mut vec: Vec<T> = if let Some(doc) = existing_doc {
95+
let mut mapping: HashMap<String, T> = if let Some(doc) = existing_doc {
9496
if doc.contains_key("data") {
9597
// Deserialize the existing data
9698
mongodb::bson::from_bson(doc.get("data").unwrap().clone())?
9799
} else {
98-
Vec::new()
100+
HashMap::new()
99101
}
100102
} else {
101-
Vec::new()
103+
HashMap::new()
102104
};
103105

104106
// Append the new data to the vec
105-
vec.push(value);
107+
mapping.insert(value_id.to_string(), value);
106108

107109
// Serialize the vec back to a BSON array
108-
let serialized_vec = mongodb::bson::to_bson(&vec)?;
110+
let serialized_vec = mongodb::bson::to_bson(&mapping)?;
109111

110112
// Create or update the document
111113
let update = doc! {
@@ -135,6 +137,7 @@ impl KvStoreConnection for MongoDbConn {
135137
async fn set_data_with_expiry<T: Serialize + std::marker::Send + DeserializeOwned>(
136138
&mut self,
137139
key: &str,
140+
value_id: &str,
138141
value: T,
139142
seconds: usize,
140143
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
@@ -151,18 +154,18 @@ impl KvStoreConnection for MongoDbConn {
151154
let filter = doc! { "_id": key };
152155
let existing_doc = collection.find_one(filter.clone(), None).await?;
153156

154-
let mut vec: Vec<T> = if let Some(doc) = existing_doc {
157+
let mut mapping: HashMap<String, T> = if let Some(doc) = existing_doc {
155158
// Deserialize the existing data
156159
mongodb::bson::from_bson(doc.get("data").unwrap().clone())?
157160
} else {
158-
Vec::new()
161+
HashMap::new()
159162
};
160163

161164
// Append the new data to the vec
162-
vec.push(value);
165+
mapping.insert(value_id.to_string(), value);
163166

164167
// Serialize the vec back to a BSON array
165-
let serialized_vec = mongodb::bson::to_bson(&vec)?;
168+
let serialized_vec = mongodb::bson::to_bson(&mapping)?;
166169

167170
// Calculate the expiry time
168171
let expiry_time = (seconds * 1000) as i64;
@@ -190,36 +193,68 @@ impl KvStoreConnection for MongoDbConn {
190193
Ok(())
191194
}
192195

193-
async fn delete_data(
196+
async fn del_data(
194197
&mut self,
195198
key: &str,
199+
value_id: Option<&str>,
196200
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
197201
// Tracing
198-
let span = span!(Level::TRACE, "MongoDbConn::delete_data");
202+
let span = span!(Level::TRACE, "MongoDbConn::del_data");
199203
let _enter = span.enter();
200204

201205
let collection = self
202206
.client
203207
.database(&self.index.db_name)
204208
.collection::<Document>(&self.index.coll_name);
205209

210+
// Build the filter based on the key
206211
let filter = doc! { "_id": key };
207-
match collection.delete_one(filter, None).await {
208-
Ok(_) => (),
209-
Err(e) => {
210-
event!(Level::ERROR, "Failed to delete data with error: {e}");
211-
}
212-
};
213212

214-
trace!("Data deleted successfully");
213+
// If value_id is provided, we need to fetch the document and update it
214+
if let Some(value_id) = value_id {
215+
let update = doc! {
216+
"$unset": {
217+
&format!("data.{}", value_id): ""
218+
}
219+
};
220+
221+
match collection.find_one_and_update(filter, update, None).await {
222+
Ok(result) => {
223+
if let Some(_) = result {
224+
// Document was found and updated, log success or handle as needed
225+
trace!("Data updated successfully");
226+
} else {
227+
// Document not found
228+
event!(Level::ERROR, "Document not found for key: {}", key);
229+
}
230+
}
231+
Err(e) => {
232+
// Handle error from MongoDB
233+
event!(Level::ERROR, "Failed to update data with error: {:?}", e);
234+
return Err(Box::new(e));
235+
}
236+
}
237+
} else {
238+
// value_id is None, so delete the entire document
239+
match collection.delete_one(filter.clone(), None).await {
240+
Ok(_) => {
241+
trace!("Data deleted successfully");
242+
}
243+
Err(e) => {
244+
event!(Level::ERROR, "Failed to delete data with error: {:?}", e);
245+
return Err(Box::new(e));
246+
}
247+
};
248+
}
215249

216250
Ok(())
217251
}
218252

219-
async fn get_data<T: DeserializeOwned>(
253+
async fn get_data<T: Clone + DeserializeOwned>(
220254
&mut self,
221255
key: &str,
222-
) -> Result<Option<Vec<T>>, Box<dyn std::error::Error + Send + Sync>> {
256+
value_id: Option<&str>,
257+
) -> Result<Option<HashMap<String, T>>, Box<dyn std::error::Error + Send + Sync>> {
223258
// Tracing
224259
let span = span!(Level::TRACE, "MongoDbConn::get_data");
225260
let _enter = span.enter();
@@ -241,8 +276,22 @@ impl KvStoreConnection for MongoDbConn {
241276

242277
if let Some(doc) = doc_find {
243278
// Deserialize the existing data
244-
let vec: Vec<T> = mongodb::bson::from_bson(doc.get("data").unwrap().clone())?;
245-
return Ok(Some(vec));
279+
let mapping: HashMap<String, T> =
280+
mongodb::bson::from_bson(doc.get("data").unwrap().clone())?;
281+
282+
if let Some(id) = value_id {
283+
// If value_id is provided, return only the value with the given ID
284+
if let Some(value) = mapping.get(id) {
285+
let mut result: HashMap<String, T> = HashMap::new();
286+
result.insert(id.to_string(), value.clone());
287+
return Ok(Some(result));
288+
} else {
289+
// Value with the given ID not found
290+
event!(Level::ERROR, "Value with ID {id} not found for key {key}");
291+
return Ok(None);
292+
}
293+
}
294+
return Ok(Some(mapping));
246295
}
247296

248297
warn!("Data unsuccessfully deserialized");

src/db/redis_cache.rs

+53-14
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
use std::collections::HashMap;
2+
13
use crate::db::handler::{CacheHandler, KvStoreConnection};
24
use async_trait::async_trait;
35
use redis::{aio::ConnectionManager, AsyncCommands};
46
use serde::{de::DeserializeOwned, Serialize};
7+
use tracing::{event, span, Level};
58

69
#[derive(Clone)]
710
pub struct RedisCacheConn {
@@ -34,22 +37,23 @@ impl KvStoreConnection for RedisCacheConn {
3437
async fn set_data<T: Serialize + DeserializeOwned + Send>(
3538
&mut self,
3639
key: &str,
40+
value_id: &str,
3741
value: T,
3842
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
3943
let exists: bool = self.connection.exists(key).await?;
4044

41-
let mut vec: Vec<T> = if exists {
45+
let mut mapping: HashMap<String, T> = if exists {
4246
// Get the existing data
4347
let data: String = self.connection.get(key).await?;
4448
serde_json::from_str(&data)?
4549
} else {
46-
Vec::new()
50+
HashMap::new()
4751
};
4852

4953
// Append the new data to the vec
50-
vec.push(value);
54+
mapping.insert(value_id.to_string(), value);
5155

52-
let serialized = serde_json::to_string(&vec)?;
56+
let serialized = serde_json::to_string(&mapping)?;
5357
self.connection.set(key, serialized).await?;
5458

5559
Ok(())
@@ -58,25 +62,26 @@ impl KvStoreConnection for RedisCacheConn {
5862
async fn set_data_with_expiry<T: Serialize + DeserializeOwned + Send>(
5963
&mut self,
6064
key: &str,
65+
value_id: &str,
6166
value: T,
6267
seconds: usize,
6368
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
6469
// Check if the key exists
6570
let exists: bool = self.connection.exists(key).await?;
6671

67-
let mut vec: Vec<T> = if exists {
72+
let mut mapping: HashMap<String, T> = if exists {
6873
// Get the existing data
6974
let data: String = self.connection.get(key).await?;
7075
serde_json::from_str(&data)?
7176
} else {
72-
Vec::new()
77+
HashMap::new()
7378
};
7479

75-
// Append the new data to the vec
76-
vec.push(value);
80+
// Append the new data to the hashmap
81+
mapping.insert(value_id.to_string(), value);
7782

7883
// Serialize the vec back to a string
79-
let serialized = serde_json::to_string(&vec)?;
84+
let serialized = serde_json::to_string(&mapping)?;
8085

8186
// Set the data back to Redis
8287
self.connection.set(key, serialized).await?;
@@ -87,26 +92,60 @@ impl KvStoreConnection for RedisCacheConn {
8792
Ok(())
8893
}
8994

90-
async fn delete_data(
95+
async fn del_data(
9196
&mut self,
9297
key: &str,
98+
value_id: Option<&str>,
9399
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
100+
if let Some(value_id) = value_id {
101+
let exists: bool = self.connection.exists(key).await?;
102+
103+
if exists {
104+
let mut mapping: HashMap<String, String> = self.get_data(key, None).await?.unwrap();
105+
mapping.remove(value_id);
106+
let serialized = serde_json::to_string(&mapping)?;
107+
self.connection.set(key, serialized).await?;
108+
}
109+
return Ok(());
110+
}
111+
94112
let _: () = self.connection.del(key).await?;
95113
Ok(())
96114
}
97115

98-
async fn get_data<T: DeserializeOwned>(
116+
async fn get_data<T: Clone + DeserializeOwned>(
99117
&mut self,
100118
key: &str,
101-
) -> Result<Option<Vec<T>>, Box<dyn std::error::Error + Send + Sync>> {
119+
value_id: Option<&str>,
120+
) -> Result<Option<HashMap<String, T>>, Box<dyn std::error::Error + Send + Sync>> {
121+
let span = span!(Level::TRACE, "MongoDbConn::get_data");
122+
let _enter = span.enter();
123+
102124
// Check if the key exists
103125
let exists: bool = self.connection.exists(key).await?;
104126

105127
if exists {
106128
// Get the existing data
107129
let data: String = self.connection.get(key).await?;
108-
let vec: Vec<T> = serde_json::from_str(&data)?;
109-
return Ok(Some(vec));
130+
let mapping: HashMap<String, T> = serde_json::from_str(&data)?;
131+
132+
if let Some(value_id) = value_id {
133+
let value = mapping.get(value_id);
134+
if let Some(value) = value {
135+
let mut new_mapping: HashMap<String, T> = HashMap::new();
136+
new_mapping.insert(value_id.to_string(), value.clone());
137+
return Ok(Some(new_mapping));
138+
} else {
139+
// Value with the given ID not found
140+
event!(
141+
Level::ERROR,
142+
"Value with ID {value_id} not found for key {key}"
143+
);
144+
return Ok(None);
145+
}
146+
}
147+
148+
return Ok(Some(mapping));
110149
}
111150

112151
Ok(None)

0 commit comments

Comments
 (0)