1use crate::ports::required::{InMemoryClient, KVSClient, HttpClient};
2use crate::core::fixed_bits;
3use serde_json::Value;
4use std::collections::HashMap;
5
6pub struct Store<'a> {
7 in_memory: Option<&'a dyn InMemoryClient>,
8 kvs: Option<&'a dyn KVSClient>,
9 http: Option<&'a dyn HttpClient>,
10}
11
12impl<'a> Store<'a> {
13 pub fn new() -> Self {
14 Self {
15 in_memory: None,
16 kvs: None,
17 http: None,
18 }
19 }
20
21 pub fn with_in_memory(mut self, client: &'a dyn InMemoryClient) -> Self {
22 self.in_memory = Some(client);
23 self
24 }
25
26 pub fn with_kvs(mut self, client: &'a dyn KVSClient) -> Self {
27 self.kvs = Some(client);
28 self
29 }
30
31 pub fn with_http(mut self, client: &'a dyn HttpClient) -> Self {
32 self.http = Some(client);
33 self
34 }
35
36 pub fn get(&self, store_config: &HashMap<String, Value>) -> Option<Value> {
37 let client = store_config.get("client")?.as_u64()?;
38
39 match client {
40 fixed_bits::CLIENT_IN_MEMORY => {
41 let in_memory = self.in_memory.as_ref()?;
42 let key = store_config.get("key")?.as_str()?;
43 in_memory.get(key)
44 }
45 fixed_bits::CLIENT_KVS => {
46 let kvs = self.kvs.as_ref()?;
47 let key = store_config.get("key")?.as_str()?;
48 let value_str = kvs.get(key)?;
49 serde_json::from_str(&value_str).ok()
50 }
51 fixed_bits::CLIENT_HTTP => {
52 let http = self.http.as_ref()?;
53 let url = store_config.get("url")?.as_str()?;
54 let headers = store_config
55 .get("headers")
56 .and_then(|v| v.as_object())
57 .map(|obj| obj.iter()
58 .filter_map(|(k, v)| v.as_str().map(|s| (k.clone(), s.to_string())))
59 .collect::<HashMap<String, String>>());
60 http.get(url, headers.as_ref())
61 }
62 _ => None,
63 }
64 }
65
66 pub fn set(
67 &self,
68 store_config: &HashMap<String, Value>,
69 value: Value,
70 ttl: Option<u64>,
71 ) -> Result<bool, String> {
72 let client = store_config
73 .get("client")
74 .and_then(|v| v.as_u64())
75 .ok_or_else(|| "Store::set: 'client' not found in store config".to_string())?;
76
77 match client {
78 fixed_bits::CLIENT_IN_MEMORY => {
79 let in_memory = self.in_memory.as_ref()
80 .ok_or_else(|| "Store::set: InMemoryClient not configured".to_string())?;
81 let key = store_config.get("key").and_then(|v| v.as_str())
82 .ok_or_else(|| "Store::set: 'key' not found in store config".to_string())?;
83 Ok(in_memory.set(key, value))
84 }
85 fixed_bits::CLIENT_KVS => {
86 let kvs = self.kvs.as_ref()
87 .ok_or_else(|| "Store::set: KVSClient not configured".to_string())?;
88 let key = store_config.get("key").and_then(|v| v.as_str())
89 .ok_or_else(|| "Store::set: 'key' not found in store config".to_string())?;
90 let serialized = serde_json::to_string(&value)
91 .map_err(|e| format!("Store::set: JSON serialize error: {}", e))?;
92 let final_ttl = ttl.or_else(|| store_config.get("ttl").and_then(|v| v.as_u64()));
93 Ok(kvs.set(key, serialized, final_ttl))
94 }
95 fixed_bits::CLIENT_HTTP => {
96 let http = self.http.as_ref()
97 .ok_or_else(|| "Store::set: HttpClient not configured".to_string())?;
98 let url = store_config.get("url").and_then(|v| v.as_str())
99 .ok_or_else(|| "Store::set: 'url' not found in store config".to_string())?;
100 let headers = store_config
101 .get("headers")
102 .and_then(|v| v.as_object())
103 .map(|obj| obj.iter()
104 .filter_map(|(k, v)| v.as_str().map(|s| (k.clone(), s.to_string())))
105 .collect::<HashMap<String, String>>());
106 Ok(http.set(url, value, headers.as_ref()))
107 }
108 _ => Err(format!("Store::set: unsupported client '{}'", client)),
109 }
110 }
111
112 pub fn delete(&self, store_config: &HashMap<String, Value>) -> Result<bool, String> {
113 let client = store_config
114 .get("client")
115 .and_then(|v| v.as_u64())
116 .ok_or_else(|| "Store::delete: 'client' not found in store config".to_string())?;
117
118 match client {
119 fixed_bits::CLIENT_IN_MEMORY => {
120 let in_memory = self.in_memory.as_ref()
121 .ok_or_else(|| "Store::delete: InMemoryClient not configured".to_string())?;
122 let key = store_config.get("key").and_then(|v| v.as_str())
123 .ok_or_else(|| "Store::delete: 'key' not found in store config".to_string())?;
124 Ok(in_memory.delete(key))
125 }
126 fixed_bits::CLIENT_KVS => {
127 let kvs = self.kvs.as_ref()
128 .ok_or_else(|| "Store::delete: KVSClient not configured".to_string())?;
129 let key = store_config.get("key").and_then(|v| v.as_str())
130 .ok_or_else(|| "Store::delete: 'key' not found in store config".to_string())?;
131 Ok(kvs.delete(key))
132 }
133 fixed_bits::CLIENT_HTTP => {
134 let http = self.http.as_ref()
135 .ok_or_else(|| "Store::delete: HttpClient not configured".to_string())?;
136 let url = store_config.get("url").and_then(|v| v.as_str())
137 .ok_or_else(|| "Store::delete: 'url' not found in store config".to_string())?;
138 let headers = store_config
139 .get("headers")
140 .and_then(|v| v.as_object())
141 .map(|obj| obj.iter()
142 .filter_map(|(k, v)| v.as_str().map(|s| (k.clone(), s.to_string())))
143 .collect::<HashMap<String, String>>());
144 Ok(http.delete(url, headers.as_ref()))
145 }
146 _ => Err(format!("Store::delete: unsupported client '{}'", client)),
147 }
148 }
149}
150
151impl<'a> Default for Store<'a> {
152 fn default() -> Self {
153 Self::new()
154 }
155}