fix: Implement persistent caching for config table retrieval (#2044)

Co-authored-by: Nitesh Balla <nitesh.balla@juspay.in>
Co-authored-by: Narayan Bhat <48803246+Narayanbhat166@users.noreply.github.com>
Co-authored-by: BallaNitesh <126162378+BallaNitesh@users.noreply.github.com>
This commit is contained in:
Kartikeya Hegde
2023-09-11 13:21:08 +05:30
committed by GitHub
parent 73da641b58
commit 25e82a1f7f
6 changed files with 40 additions and 78 deletions

View File

@ -25,7 +25,7 @@ pub async fn set_config(
pub async fn read_config(store: &dyn StorageInterface, key: &str) -> RouterResponse<api::Config> {
let config = store
.find_config_by_key_cached(key)
.find_config_by_key(key)
.await
.to_not_found_response(errors::ApiErrorResponse::ConfigNotFound)?;
Ok(ApplicationResponse::Json(config.foreign_into()))
@ -36,7 +36,7 @@ pub async fn update_config(
config_update: &api::ConfigUpdate,
) -> RouterResponse<api::Config> {
let config = store
.update_config_cached(&config_update.key, config_update.foreign_into())
.update_config_by_key(&config_update.key, config_update.foreign_into())
.await
.to_not_found_response(errors::ApiErrorResponse::ConfigNotFound)?;
Ok(ApplicationResponse::Json(config.foreign_into()))

View File

@ -106,7 +106,7 @@ where
let connector_api_version = if supported_connector.contains(&connector_enum) {
state
.store
.find_config_by_key_cached(&format!("connector_api_version_{connector_id}"))
.find_config_by_key(&format!("connector_api_version_{connector_id}"))
.await
.map(|value| value.config)
.ok()

View File

@ -262,7 +262,7 @@ pub async fn construct_refund_router_data<'a, F>(
let connector_api_version = if supported_connector.contains(&connector_enum) {
state
.store
.find_config_by_key_cached(&format!("connector_api_version_{connector_id}"))
.find_config_by_key(&format!("connector_api_version_{connector_id}"))
.await
.map(|value| value.config)
.ok()

View File

@ -29,7 +29,7 @@ pub async fn lookup_webhook_event(
Ok(merchant_webhook_config) => merchant_webhook_config.contains(event),
Err(..) => {
//if failed to fetch from redis. fetch from db and populate redis
db.find_config_by_key_cached(&redis_key)
db.find_config_by_key(&redis_key)
.await
.map(|config| {
if let Ok(set) =

View File

@ -25,7 +25,7 @@ pub trait ConfigInterface {
key: &str,
) -> CustomResult<storage::Config, errors::StorageError>;
async fn find_config_by_key_cached(
async fn find_config_by_key_from_db(
&self,
key: &str,
) -> CustomResult<storage::Config, errors::StorageError>;
@ -36,12 +36,6 @@ pub trait ConfigInterface {
config_update: storage::ConfigUpdate,
) -> CustomResult<storage::Config, errors::StorageError>;
async fn update_config_cached(
&self,
key: &str,
config_update: storage::ConfigUpdate,
) -> CustomResult<storage::Config, errors::StorageError>;
async fn delete_config_by_key(&self, key: &str) -> CustomResult<bool, errors::StorageError>;
}
@ -55,32 +49,8 @@ impl ConfigInterface for Store {
config.insert(&conn).await.map_err(Into::into).into_report()
}
//fetch directly from DB
async fn find_config_by_key(
&self,
key: &str,
) -> CustomResult<storage::Config, errors::StorageError> {
let conn = connection::pg_connection_write(self).await?;
storage::Config::find_by_key(&conn, key)
.await
.map_err(Into::into)
.into_report()
}
async fn update_config_by_key(
&self,
key: &str,
config_update: storage::ConfigUpdate,
) -> CustomResult<storage::Config, errors::StorageError> {
let conn = connection::pg_connection_write(self).await?;
storage::Config::update_by_key(&conn, key, config_update)
.await
.map_err(Into::into)
.into_report()
}
//update in DB and remove in redis and cache
async fn update_config_cached(
async fn update_config_by_key(
&self,
key: &str,
config_update: storage::ConfigUpdate,
@ -91,12 +61,28 @@ impl ConfigInterface for Store {
.await
}
//check in cache, then redis then finally DB, and on the way back populate redis and cache
async fn find_config_by_key_cached(
async fn find_config_by_key_from_db(
&self,
key: &str,
) -> CustomResult<storage::Config, errors::StorageError> {
cache::get_or_populate_in_memory(self, key, || self.find_config_by_key(key), &CONFIG_CACHE)
let conn = connection::pg_connection_write(self).await?;
storage::Config::find_by_key(&conn, key)
.await
.map_err(Into::into)
.into_report()
}
//check in cache, then redis then finally DB, and on the way back populate redis and cache
async fn find_config_by_key(
&self,
key: &str,
) -> CustomResult<storage::Config, errors::StorageError> {
cache::get_or_populate_in_memory(
self,
key,
|| self.find_config_by_key_from_db(key),
&CONFIG_CACHE,
)
.await
}
@ -138,18 +124,6 @@ impl ConfigInterface for MockDb {
Ok(config_new)
}
async fn find_config_by_key(
&self,
key: &str,
) -> CustomResult<storage::Config, errors::StorageError> {
let configs = self.configs.lock().await;
let config = configs.iter().find(|c| c.key == key).cloned();
config.ok_or_else(|| {
errors::StorageError::ValueNotFound("cannot find config".to_string()).into()
})
}
async fn update_config_by_key(
&self,
key: &str,
@ -174,30 +148,6 @@ impl ConfigInterface for MockDb {
result
}
async fn update_config_cached(
&self,
key: &str,
config_update: storage::ConfigUpdate,
) -> CustomResult<storage::Config, errors::StorageError> {
let result = self
.configs
.lock()
.await
.iter_mut()
.find(|c| c.key == key)
.ok_or_else(|| {
errors::StorageError::ValueNotFound("cannot find config to update".to_string())
.into()
})
.map(|c| {
let config_updated =
ConfigUpdateInternal::from(config_update).create_config(c.clone());
*c = config_updated.clone();
config_updated
});
result
}
async fn delete_config_by_key(&self, key: &str) -> CustomResult<bool, errors::StorageError> {
let mut configs = self.configs.lock().await;
@ -216,7 +166,19 @@ impl ConfigInterface for MockDb {
result
}
async fn find_config_by_key_cached(
async fn find_config_by_key_from_db(
&self,
key: &str,
) -> CustomResult<storage::Config, errors::StorageError> {
let configs = self.configs.lock().await;
let config = configs.iter().find(|c| c.key == key).cloned();
config.ok_or_else(|| {
errors::StorageError::ValueNotFound("cannot find config".to_string()).into()
})
}
async fn find_config_by_key(
&self,
key: &str,
) -> CustomResult<storage::Config, errors::StorageError> {

View File

@ -124,7 +124,7 @@ pub async fn get_sync_process_schedule_time(
process_data::ConnectorPTMapping,
errors::StorageError,
> = db
.find_config_by_key_cached(&format!("pt_mapping_{connector}"))
.find_config_by_key(&format!("pt_mapping_{connector}"))
.await
.map(|value| value.config)
.and_then(|config| {