liter_llm/tenant/
in_memory.rs1use std::future::Future;
2use std::pin::Pin;
3use std::sync::Arc;
4
5use dashmap::DashMap;
6
7use super::resolver::{KeyResolver, KeyResolverError, ResolvedKey};
8
9pub struct InMemoryKeyResolver {
19 keys: Arc<DashMap<String, ResolvedKey>>,
20}
21
22impl InMemoryKeyResolver {
23 #[must_use]
25 pub fn new() -> Self {
26 Self {
27 keys: Arc::new(DashMap::new()),
28 }
29 }
30
31 #[must_use]
33 pub fn with_entries(entries: impl IntoIterator<Item = (String, ResolvedKey)>) -> Self {
34 let keys = DashMap::new();
35 for (k, v) in entries {
36 keys.insert(k, v);
37 }
38 Self { keys: Arc::new(keys) }
39 }
40
41 pub fn insert(&self, api_key: impl Into<String>, resolved: ResolvedKey) {
43 self.keys.insert(api_key.into(), resolved);
44 }
45
46 pub fn remove(&self, api_key: &str) -> Option<ResolvedKey> {
48 self.keys.remove(api_key).map(|(_, v)| v)
49 }
50}
51
52impl Default for InMemoryKeyResolver {
53 fn default() -> Self {
54 Self::new()
55 }
56}
57
58impl KeyResolver for InMemoryKeyResolver {
59 fn resolve(
60 &self,
61 api_key: String,
62 ) -> Pin<Box<dyn Future<Output = Result<ResolvedKey, KeyResolverError>> + Send + 'static>> {
63 let keys = self.keys.clone();
64 Box::pin(async move {
65 match keys.get(&api_key) {
66 None => Err(KeyResolverError::NotFound),
67 Some(entry) => {
68 if !entry.active {
69 Err(KeyResolverError::Inactive)
70 } else {
71 Ok(entry.clone())
72 }
73 }
74 }
75 })
76 }
77}