1use crate::sql::error::SqlError;
2use crate::sql::traits::EntitySqlLogic;
3use crate::PostgresClient;
4use mini_moka::sync::Cache;
5use scouter_types::DriftType;
6use sqlx::{Pool, Postgres};
7use std::sync::OnceLock;
8
9#[derive(Clone, Debug)]
10pub struct EntityCache {
11 cache: Cache<String, i32>,
12}
13
14impl EntityCache {
15 pub fn new(max_capacity: u64) -> Self {
16 let cache = Cache::new(max_capacity);
17 Self { cache }
18 }
19
20 pub async fn get_entity_id_from_uid(
27 &self,
28 pool: &Pool<Postgres>,
29 uid: &String,
30 ) -> Result<i32, SqlError> {
31 match self.cache.get(uid) {
32 Some(cached_id) => Ok(cached_id),
33 None => {
34 let entity_id = PostgresClient::get_entity_id_from_uid(pool, uid).await?;
35 self.cache.insert(uid.to_string(), entity_id);
36 Ok(entity_id)
37 }
38 }
39 }
40
41 pub async fn get_optional_entity_id_from_uid(
42 &self,
43 pool: &Pool<Postgres>,
44 uid: &String,
45 ) -> Result<Option<i32>, SqlError> {
46 match self.cache.get(uid) {
47 Some(cached_id) => Ok(Some(cached_id)),
48 None => {
49 let entity_id = PostgresClient::get_optional_entity_id_from_uid(pool, uid).await?;
50 if let Some(id) = entity_id {
51 self.cache.insert(uid.to_string(), id);
52 }
53 Ok(entity_id)
54 }
55 }
56 }
57
58 pub async fn get_entity_id_from_space_name_version_drift_type(
59 &self,
60 pool: &Pool<Postgres>,
61 space: &str,
62 name: &str,
63 version: &str,
64 drift_type: &DriftType,
65 ) -> Result<i32, SqlError> {
66 let id = PostgresClient::get_entity_id_from_space_name_version_drift_type(
67 pool,
68 space,
69 name,
70 version,
71 drift_type.to_string(),
72 )
73 .await?;
74
75 Ok(id)
76 }
77}
78
79static INSTANCE: OnceLock<EntityCache> = OnceLock::new();
80
81pub fn init_entity_cache(max_capacity: u64) {
82 INSTANCE.get_or_init(|| {
83 tracing::info!("Initializing EntityCache");
84 EntityCache::new(max_capacity)
85 });
86}
87
88pub fn entity_cache() -> &'static EntityCache {
89 INSTANCE
90 .get()
91 .expect("EntityCache is not initialized - call init_entity_cache first")
92}