diff --git a/services/feature-flags/Cargo.lock b/services/feature-flags/Cargo.lock --- a/services/feature-flags/Cargo.lock +++ b/services/feature-flags/Cargo.lock @@ -392,6 +392,12 @@ "os_str_bytes", ] +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "core-foundation" version = "0.9.3" @@ -408,6 +414,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn", +] + [[package]] name = "either" version = "1.8.1" @@ -453,6 +472,7 @@ "aws-sdk-dynamodb", "aws-types", "clap", + "derive_more", "http", "once_cell", "tokio", diff --git a/services/feature-flags/Cargo.toml b/services/feature-flags/Cargo.toml --- a/services/feature-flags/Cargo.toml +++ b/services/feature-flags/Cargo.toml @@ -12,6 +12,7 @@ aws-types = "0.51.0" aws-sdk-dynamodb = "0.21.0" clap = { version = "4.0", features = ["derive", "env"] } +derive_more = "0.99" http = "0.2" once_cell = "1.17" tokio = { version = "1.24", features = ["rt-multi-thread", "macros"]} diff --git a/services/feature-flags/src/database.rs b/services/feature-flags/src/database.rs new file mode 100644 --- /dev/null +++ b/services/feature-flags/src/database.rs @@ -0,0 +1,80 @@ +use aws_sdk_dynamodb::{model::AttributeValue, Error as DynamoDBError}; +use std::fmt::{Display, Formatter}; + +#[derive( + Debug, derive_more::Display, derive_more::From, derive_more::Error, +)] +pub enum Error { + #[display(...)] + AwsSdk(DynamoDBError), + #[display(...)] + Attribute(DBItemError), +} + +#[derive(Debug, derive_more::Error, derive_more::Constructor)] +pub struct DBItemError { + attribute_name: &'static str, + attribute_value: Option, + attribute_error: DBItemAttributeError, +} + +impl Display for DBItemError { + fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { + match &self.attribute_error { + DBItemAttributeError::Missing => { + write!(f, "Attribute {} is missing", self.attribute_name) + } + DBItemAttributeError::IncorrectType => write!( + f, + "Value for attribute {} has incorrect type: {:?}", + self.attribute_name, self.attribute_value + ), + } + } +} + +#[derive(Debug, derive_more::Display, derive_more::Error)] +pub enum DBItemAttributeError { + #[display(...)] + Missing, + #[display(...)] + IncorrectType, +} + +fn _parse_string_attribute( + attribute_name: &'static str, + attribute_value: Option, +) -> Result { + match attribute_value { + Some(AttributeValue::S(value)) => Ok(value), + Some(_) => Err(DBItemError::new( + attribute_name, + attribute_value, + DBItemAttributeError::IncorrectType, + )), + None => Err(DBItemError::new( + attribute_name, + attribute_value, + DBItemAttributeError::Missing, + )), + } +} + +fn _parse_bool_attribute( + attribute_name: &'static str, + attribute_value: Option, +) -> Result { + match attribute_value { + Some(AttributeValue::Bool(value)) => Ok(value), + Some(_) => Err(DBItemError::new( + attribute_name, + attribute_value, + DBItemAttributeError::IncorrectType, + )), + None => Err(DBItemError::new( + attribute_name, + attribute_value, + DBItemAttributeError::Missing, + )), + } +} diff --git a/services/feature-flags/src/main.rs b/services/feature-flags/src/main.rs --- a/services/feature-flags/src/main.rs +++ b/services/feature-flags/src/main.rs @@ -4,6 +4,7 @@ pub mod config; pub mod constants; +pub mod database; fn configure_logging() -> Result<()> { let filter = EnvFilter::builder()