Skip to content

Commit f5d7dd0

Browse files
committed
GETKEY implementation
1 parent 37c618f commit f5d7dd0

File tree

6 files changed

+131
-5
lines changed

6 files changed

+131
-5
lines changed

ahnlich/server/src/engine/store.rs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ impl StoreHandler {
172172
keys: Vec<StoreKey>,
173173
) -> Result<Vec<(StoreKey, StoreValue)>, ServerError> {
174174
let store = self.get(store_name)?;
175-
Ok(store.get_keys(keys))
175+
store.get_keys(keys)
176176
}
177177

178178
/// Matches SET - adds new entries into a particular store
@@ -279,12 +279,27 @@ impl Store {
279279
}
280280

281281
/// Gets a bunch of store keys from the store
282-
fn get_keys(&self, val: Vec<StoreKey>) -> Vec<(StoreKey, StoreValue)> {
282+
fn get_keys(&self, val: Vec<StoreKey>) -> Result<Vec<(StoreKey, StoreValue)>, ServerError> {
283283
if val.is_empty() {
284-
return vec![];
284+
return Ok(vec![]);
285285
}
286-
let keys = val.iter().map(From::from);
287-
self.get(keys)
286+
// return error if dimensions do not match
287+
let keys = val
288+
.into_iter()
289+
.map(|key| {
290+
let store_dimension = self.dimension.get();
291+
let input_dimension = key.dimension();
292+
if input_dimension != store_dimension {
293+
return Err(ServerError::StoreDimensionMismatch {
294+
store_dimension,
295+
input_dimension,
296+
});
297+
}
298+
Ok(key)
299+
})
300+
.collect::<Result<Vec<StoreKey>, ServerError>>()?;
301+
let keys = keys.iter().map(From::from);
302+
Ok(self.get(keys))
288303
}
289304

290305
/// Gets a bunch of store entries that matches a predicate condition

ahnlich/server/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,11 @@ impl ServerTask {
208208
.set_in_store(&store, inputs)
209209
.map(ServerResponse::Set)
210210
.map_err(|e| format!("{e}")),
211+
Query::GetKey { store, keys } => self
212+
.store_handler
213+
.get_key_in_store(&store, keys)
214+
.map(ServerResponse::GetKey)
215+
.map_err(|e| format!("{e}")),
211216
_ => Err("Response not implemented".to_string()),
212217
})
213218
}

ahnlich/server/tests/server_test.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,102 @@ async fn test_set_in_store() {
202202
query_server_assert_result(&mut reader, message, expected).await
203203
}
204204

205+
#[tokio::test]
206+
async fn test_get_key() {
207+
let server = server::Server::new(&ServerConfig::default())
208+
.await
209+
.expect("Could not initialize server");
210+
let address = server.local_addr().expect("Could not get local addr");
211+
let _ = tokio::spawn(async move { server.start().await });
212+
// Allow some time for the server to start
213+
tokio::time::sleep(Duration::from_millis(100)).await;
214+
let message = ServerQuery::from_queries(&[
215+
// should error as store does not yet exist
216+
Query::GetKey {
217+
store: StoreName("Main".to_string()),
218+
keys: vec![],
219+
},
220+
Query::CreateStore {
221+
store: StoreName("Main".to_string()),
222+
dimension: NonZeroUsize::new(2).unwrap(),
223+
create_predicates: HashSet::new(),
224+
error_if_exists: true,
225+
},
226+
Query::Set {
227+
store: StoreName("Main".to_string()),
228+
inputs: vec![
229+
(
230+
StoreKey(array![1.0, 0.2]),
231+
HashMap::from_iter([(
232+
MetadataKey::new("title".into()),
233+
MetadataValue::new("sorcerer".into()),
234+
)]),
235+
),
236+
(
237+
StoreKey(array![1.2, 0.3]),
238+
HashMap::from_iter([(
239+
MetadataKey::new("title".into()),
240+
MetadataValue::new("elf".into()),
241+
)]),
242+
),
243+
],
244+
},
245+
// should error as dimension mismatch
246+
Query::GetKey {
247+
store: StoreName("Main".to_string()),
248+
keys: vec![
249+
StoreKey(array![0.2, 0.3, 0.4]),
250+
StoreKey(array![0.2, 0.3, 0.4, 0.6]),
251+
StoreKey(array![0.4, 0.6]),
252+
],
253+
},
254+
// should not error however the keys do not exist so should be empty
255+
Query::GetKey {
256+
store: StoreName("Main".to_string()),
257+
keys: vec![StoreKey(array![0.4, 0.6]), StoreKey(array![0.2, 0.5])],
258+
},
259+
// Gets back the existing key in order
260+
Query::GetKey {
261+
store: StoreName("Main".to_string()),
262+
keys: vec![
263+
StoreKey(array![1.2, 0.3]),
264+
StoreKey(array![0.4, 0.6]),
265+
StoreKey(array![1.0, 0.2]),
266+
],
267+
},
268+
]);
269+
let mut expected = ServerResult::with_capacity(6);
270+
expected.push(Err("Store Main not found".to_string()));
271+
expected.push(Ok(ServerResponse::Unit));
272+
expected.push(Ok(ServerResponse::Set(StoreUpsert {
273+
inserted: 2,
274+
updated: 0,
275+
})));
276+
expected.push(Err(
277+
"Store dimension is [2], input dimension of [3] was specified".to_string(),
278+
));
279+
expected.push(Ok(ServerResponse::GetKey(vec![])));
280+
expected.push(Ok(ServerResponse::GetKey(vec![
281+
(
282+
StoreKey(array![1.2, 0.3]),
283+
HashMap::from_iter([(
284+
MetadataKey::new("title".into()),
285+
MetadataValue::new("elf".into()),
286+
)]),
287+
),
288+
(
289+
StoreKey(array![1.0, 0.2]),
290+
HashMap::from_iter([(
291+
MetadataKey::new("title".into()),
292+
MetadataValue::new("sorcerer".into()),
293+
)]),
294+
),
295+
])));
296+
let stream = TcpStream::connect(address).await.unwrap();
297+
let mut reader = BufReader::new(stream);
298+
query_server_assert_result(&mut reader, message, expected).await
299+
}
300+
205301
#[tokio::test]
206302
async fn test_drop_stores() {
207303
let server = server::Server::new(&ServerConfig::default())

ahnlich/types/src/keyval.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ pub type StoreValue = StdHashMap<MetadataKey, MetadataValue>;
2525
#[serde(transparent)]
2626
pub struct StoreKey(pub Array1<f64>);
2727

28+
impl StoreKey {
29+
pub fn dimension(&self) -> usize {
30+
self.0.len()
31+
}
32+
}
33+
2834
impl Eq for StoreKey {}
2935

3036
impl PartialEq for StoreKey {

ahnlich/types/src/query.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub enum Query {
2525
error_if_exists: bool,
2626
},
2727
GetKey {
28+
store: StoreName,
2829
keys: Vec<StoreKey>,
2930
},
3031
GetPred {

ahnlich/types/src/server.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::bincode::BinCodeSerAndDeser;
2+
use crate::keyval::StoreKey;
23
use crate::keyval::StoreName;
4+
use crate::keyval::StoreValue;
35
use serde::Deserialize;
46
use serde::Serialize;
57
use std::collections::HashSet;
@@ -17,6 +19,7 @@ pub enum ServerResponse {
1719
StoreList(HashSet<StoreInfo>),
1820
InfoServer(ServerInfo),
1921
Set(StoreUpsert),
22+
GetKey(Vec<(StoreKey, StoreValue)>),
2023
// TODO: Define return types for queries, e.t.c
2124
}
2225

0 commit comments

Comments
 (0)