diff --git a/services/feature-flags/src/constants.rs b/services/feature-flags/src/constants.rs --- a/services/feature-flags/src/constants.rs +++ b/services/feature-flags/src/constants.rs @@ -25,3 +25,6 @@ pub const FEATURE_FLAGS_FEATURE_FIELD: &str = "feature"; pub const FEATURE_FLAGS_STAFF_FIELD: &str = "staff"; pub const FEATURE_FLAGS_NON_STAFF_FIELD: &str = "non-staff"; + +pub const PLATFORM_IOS: &str = "IOS"; +pub const PLATFORM_ANDROID: &str = "ANDROID"; diff --git a/services/feature-flags/src/database.rs b/services/feature-flags/src/database.rs --- a/services/feature-flags/src/database.rs +++ b/services/feature-flags/src/database.rs @@ -1,10 +1,14 @@ use crate::constants::{ FEATURE_FLAGS_CONFIG_FIELD, FEATURE_FLAGS_FEATURE_FIELD, - FEATURE_FLAGS_NON_STAFF_FIELD, FEATURE_FLAGS_STAFF_FIELD, + FEATURE_FLAGS_NON_STAFF_FIELD, FEATURE_FLAGS_PLATFORM_FIELD, + FEATURE_FLAGS_STAFF_FIELD, FEATURE_FLAGS_TABLE_NAME, PLATFORM_ANDROID, + PLATFORM_IOS, }; -use aws_sdk_dynamodb::model::AttributeValue; -use comm_services_lib::database::{self, DBItemError}; +use aws_sdk_dynamodb::model::{AttributeValue, Select}; +use comm_services_lib::database::{self, DBItemError, Error}; use std::collections::HashMap; +use std::sync::Arc; +use tracing::error; #[derive(Debug)] pub struct CodeVersionSpecificFeatureConfig { @@ -12,7 +16,7 @@ pub non_staff: bool, } -fn _parse_code_version_specific_feature_config( +fn parse_code_version_specific_feature_config( value: Option, ) -> Result { let mut code_version_config_map = @@ -34,7 +38,7 @@ pub config: HashMap, } -fn _parse_feature_config( +fn parse_feature_config( mut attribute_value: HashMap, ) -> Result { let feature_name = database::parse_string_attribute( @@ -50,7 +54,7 @@ let code_version: i32 = database::parse_number("code_version", code_version_string.as_str())?; let version_config = - _parse_code_version_specific_feature_config(Some(code_version_config))?; + parse_code_version_specific_feature_config(Some(code_version_config))?; config.insert(code_version, version_config); } Ok(FeatureConfig { @@ -58,3 +62,59 @@ config, }) } + +pub enum Platform { + IOS, + ANDROID, +} + +#[derive(Clone)] +pub struct DatabaseClient { + client: Arc, +} + +impl DatabaseClient { + pub fn new(aws_config: &aws_types::SdkConfig) -> Self { + DatabaseClient { + client: Arc::new(aws_sdk_dynamodb::Client::new(aws_config)), + } + } + + pub async fn get_features_configuration( + &self, + platform: Platform, + ) -> Result, Error> { + let platform_value = match platform { + Platform::IOS => PLATFORM_IOS, + Platform::ANDROID => PLATFORM_ANDROID, + }; + let result = self + .client + .query() + .select(Select::AllAttributes) + .table_name(FEATURE_FLAGS_TABLE_NAME) + .consistent_read(true) + .key_condition_expression("#platform = :platform") + .expression_attribute_names("#platform", FEATURE_FLAGS_PLATFORM_FIELD) + .expression_attribute_values( + ":platform", + AttributeValue::S(platform_value.to_string()), + ) + .send() + .await + .map_err(|e| { + error!("DynamoDB client failed to find feature flags configuration"); + Error::AwsSdk(e.into()) + })?; + if let Some(items) = result.items { + let mut config = HashMap::new(); + for item in items { + let feature_config = parse_feature_config(item)?; + config.insert(feature_config.name.clone(), feature_config); + } + Ok(config) + } else { + Ok(HashMap::new()) + } + } +}