mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-11-01 02:57:02 +08:00 
			
		
		
		
	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:
		| @ -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())) | ||||
|  | ||||
| @ -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() | ||||
|  | ||||
| @ -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() | ||||
|  | ||||
| @ -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) = | ||||
|  | ||||
| @ -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> { | ||||
|  | ||||
| @ -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| { | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Kartikeya Hegde
					Kartikeya Hegde