1use std::any::Any;
9
10use async_trait::async_trait;
11use bytes::Bytes;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum StoreKind {
16 KeyValue,
17 Window,
18 Session,
19 Versioned,
20}
21
22pub enum Iq2Query {
33 Key { key: Box<dyn Any + Send + Sync> },
35 Range {
38 lo: Option<Box<dyn Any + Send + Sync>>,
39 hi: Option<Box<dyn Any + Send + Sync>>,
40 descending: bool,
41 },
42 WindowKey {
45 key: Box<dyn Any + Send + Sync>,
46 from_ts: i64,
47 to_ts: i64,
48 },
49 WindowRange {
53 lo: Option<Box<dyn Any + Send + Sync>>,
54 hi: Option<Box<dyn Any + Send + Sync>>,
55 from_ts: i64,
56 to_ts: i64,
57 },
58 VersionedKey {
62 key: Box<dyn Any + Send + Sync>,
63 as_of: Option<i64>,
64 },
65 MultiVersionedKey {
70 key: Box<dyn Any + Send + Sync>,
71 from_ts: Option<i64>,
72 to_ts: Option<i64>,
73 descending: bool,
74 },
75}
76
77#[derive(Debug, Clone, PartialEq, Eq)]
81pub enum Iq2Failure {
82 UnknownQueryType,
84 KeyTypeMismatch,
86}
87
88#[doc(hidden)]
93#[async_trait]
94pub trait IqQueryable: Send + Sync {
95 fn kind(&self) -> StoreKind;
96
97 async fn iq_kv_get(&self, _key: &[u8]) -> Option<Bytes> {
98 None
99 }
100 async fn iq_kv_range(&self, _lo: &[u8], _hi: &[u8]) -> Vec<(Bytes, Bytes)> {
102 Vec::new()
103 }
104 async fn iq_kv_all(&self) -> Vec<(Bytes, Bytes)> {
105 Vec::new()
106 }
107 async fn iq_kv_approx_count(&self) -> u64 {
108 0
109 }
110
111 async fn iq_window_fetch_single(&self, _key: &[u8], _window_start: i64) -> Option<Bytes> {
112 None
113 }
114 async fn iq_window_fetch(
116 &self,
117 _key: &[u8],
118 _time_from: i64,
119 _time_to: i64,
120 ) -> Vec<(i64, Bytes)> {
121 Vec::new()
122 }
123
124 async fn iq_session_fetch_key(&self, _key: &[u8]) -> Vec<((i64, i64), Bytes)> {
126 Vec::new()
127 }
128
129 async fn iq_versioned_get(&self, _key: &[u8]) -> Option<(i64, Option<i64>, Bytes)> {
131 None
132 }
133 async fn iq_versioned_get_as_of(
135 &self,
136 _key: &[u8],
137 _as_of: i64,
138 ) -> Option<(i64, Option<i64>, Bytes)> {
139 None
140 }
141
142 async fn iq2_execute(&self, _query: &Iq2Query) -> Result<Box<dyn Any + Send>, Iq2Failure> {
147 Err(Iq2Failure::UnknownQueryType)
148 }
149}
150
151#[cfg(test)]
152mod tests {
153 use krabka_units::prelude::*;
154
155 use super::*;
156 use crate::{
157 processor::serde::{I64Serde, Serde, StringSerde},
158 store::{
159 api::{KeyValueStore, StateStore},
160 kv::KeyValueBytesStore,
161 session::{SessionBytesStore, SessionStore},
162 window::{WindowBytesStore, WindowStore},
163 },
164 };
165
166 #[tokio::test]
167 async fn kv_get_range_all_count_inclusive() {
168 let mut s = KeyValueBytesStore::<String, i64>::in_memory(
169 "c".into(),
170 Box::new(StringSerde),
171 Box::new(I64Serde),
172 "c-changelog".into(),
173 );
174 for (k, v) in [("a", 1), ("b", 2), ("c", 3)] {
175 s.put(k.into(), v).await;
176 }
177 let q: &dyn IqQueryable = s.as_iq().unwrap();
178 assert_eq!(q.iq_kv_get(b"b").await, Some(I64Serde.serialize("t", &2)));
179 assert_eq!(q.iq_kv_get(b"z").await, None);
180 let r = q.iq_kv_range(b"a", b"b").await; assert_eq!(r.len(), 2);
182 assert_eq!(r[0].0, bytes::Bytes::from_static(b"a"));
183 assert_eq!(r[1].0, bytes::Bytes::from_static(b"b"));
184 assert!(q.iq_kv_range(b"c", b"a").await.is_empty()); assert_eq!(q.iq_kv_all().await.len(), 3);
186 assert_eq!(q.iq_kv_approx_count().await, 3);
187 }
188
189 #[tokio::test]
190 async fn window_fetch_point_and_range() {
191 let mut s = WindowBytesStore::<String, i64>::in_memory(
192 "w".into(),
193 Box::new(StringSerde),
194 Box::new(I64Serde),
195 "w-changelog".into(),
196 secs(1),
197 );
198 s.put("k".into(), 0, 10, 5).await;
199 s.put("k".into(), 1000, 20, 1005).await;
200 let q: &dyn IqQueryable = s.as_iq().unwrap();
201 assert_eq!(
202 q.iq_window_fetch_single(b"k", 0).await,
203 Some(I64Serde.serialize("t", &10))
204 );
205 assert_eq!(q.iq_window_fetch_single(b"k", 500).await, None);
206 let r = q.iq_window_fetch(b"k", 0, 1000).await;
207 assert_eq!(r.iter().map(|(t, _)| *t).collect::<Vec<_>>(), vec![0, 1000]);
208 }
209
210 #[tokio::test]
211 async fn versioned_get_latest_and_as_of() {
212 use crate::store::versioned::{VersionedBytesStore, VersionedKeyValueStore};
213 let mut s = VersionedBytesStore::<String, i64>::in_memory(
214 "v".into(),
215 secs(1_000),
216 Box::new(StringSerde),
217 Box::new(I64Serde),
218 "v-changelog".into(),
219 );
220 s.put("k".into(), Some(10), 100).await;
221 s.put("k".into(), Some(20), 200).await;
222 let q: &dyn IqQueryable = s.as_iq().unwrap();
223 assert_eq!(q.kind(), StoreKind::Versioned);
224 let (vf, vt, raw) = q.iq_versioned_get(b"k").await.unwrap();
225 assert_eq!((vf, vt), (200, None));
226 assert_eq!(raw, I64Serde.serialize("t", &20));
227 let (vf2, vt2, raw2) = q.iq_versioned_get_as_of(b"k", 150).await.unwrap();
228 assert_eq!((vf2, vt2), (100, Some(200)));
229 assert_eq!(raw2, I64Serde.serialize("t", &10));
230 assert_eq!(q.iq_versioned_get_as_of(b"k", 50).await, None);
231 }
232
233 #[tokio::test]
234 async fn session_fetch_key_carries_start_end() {
235 let mut s = SessionBytesStore::<String, i64>::in_memory(
236 "s".into(),
237 Box::new(StringSerde),
238 Box::new(I64Serde),
239 "s-changelog".into(),
240 );
241 s.put("k".into(), 0, 10, 1).await;
242 s.put("k".into(), 20, 30, 2).await;
243 let q: &dyn IqQueryable = s.as_iq().unwrap();
244 let r = q.iq_session_fetch_key(b"k").await;
245 let windows: Vec<(i64, i64)> = r.iter().map(|((st, en), _)| (*st, *en)).collect();
246 assert!(windows.contains(&(0, 10)) && windows.contains(&(20, 30)));
247 }
248
249 #[tokio::test]
250 async fn iq2_execute_default_is_unknown_query_type() {
251 use super::{Iq2Failure, Iq2Query};
252 let s = SessionBytesStore::<String, i64>::in_memory(
254 "s".into(),
255 Box::new(StringSerde),
256 Box::new(I64Serde),
257 "s-changelog".into(),
258 );
259 let q: &dyn IqQueryable = s.as_iq().unwrap();
260 let query = Iq2Query::Key {
261 key: Box::new("k".to_string()),
262 };
263 assert_eq!(
264 q.iq2_execute(&query).await.err(),
265 Some(Iq2Failure::UnknownQueryType)
266 );
267
268 let mv = Iq2Query::MultiVersionedKey {
270 key: Box::new("k".to_string()),
271 from_ts: None,
272 to_ts: None,
273 descending: false,
274 };
275 assert_eq!(
276 q.iq2_execute(&mv).await.err(),
277 Some(Iq2Failure::UnknownQueryType)
278 );
279 }
280}