use std::collections::HashMap;
use std::time::Duration;
use azure_core::http::headers::{HeaderName, HeaderValue};
use azure_data_cosmos_macros::CosmosOptions;
use crate::{
models::ThroughputControlGroupName,
options::{
ContentResponseOnWrite, EndToEndOperationLatencyPolicy, ExcludedRegions,
ReadConsistencyStrategy,
},
};
#[derive(CosmosOptions, Clone, Debug)]
#[options(layers(runtime, account, operation))]
#[non_exhaustive]
pub struct OperationOptions {
#[option(env = "AZURE_COSMOS_READ_CONSISTENCY_STRATEGY")]
pub read_consistency_strategy: Option<ReadConsistencyStrategy>,
pub excluded_regions: Option<ExcludedRegions>,
#[option(env = "AZURE_COSMOS_CONTENT_RESPONSE_ON_WRITE")]
pub content_response_on_write: Option<ContentResponseOnWrite>,
pub throughput_control_group: Option<ThroughputControlGroupName>,
pub end_to_end_latency_policy: Option<EndToEndOperationLatencyPolicy>,
#[option(env = "AZURE_COSMOS_MAX_FAILOVER_RETRY_COUNT")]
pub max_failover_retry_count: Option<u32>,
pub endpoint_unavailability_ttl: Option<Duration>,
pub session_capturing_disabled: Option<bool>,
#[option(env = "AZURE_COSMOS_MAX_SESSION_RETRY_COUNT")]
pub max_session_retry_count: Option<u32>,
custom_headers: Option<HashMap<HeaderName, HeaderValue>>,
}
impl OperationOptions {
pub fn with_custom_headers(mut self, headers: HashMap<HeaderName, HeaderValue>) -> Self {
self.custom_headers = Some(headers);
self
}
pub fn custom_headers(&self) -> Option<&HashMap<HeaderName, HeaderValue>> {
self.custom_headers.as_ref()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_operation_options() {
let options = OperationOptions::default();
assert!(options.read_consistency_strategy.is_none());
assert!(options.excluded_regions.is_none());
assert!(options.content_response_on_write.is_none());
assert!(options.throughput_control_group.is_none());
assert!(options.max_failover_retry_count.is_none());
assert!(options.max_session_retry_count.is_none());
}
#[test]
fn builder_creates_options() {
let options = OperationOptionsBuilder::new()
.with_content_response_on_write(ContentResponseOnWrite::Disabled)
.with_read_consistency_strategy(ReadConsistencyStrategy::Session)
.with_max_failover_retry_count(5)
.with_max_session_retry_count(3)
.build();
assert_eq!(
options.content_response_on_write,
Some(ContentResponseOnWrite::Disabled)
);
assert_eq!(
options.read_consistency_strategy,
Some(ReadConsistencyStrategy::Session)
);
assert_eq!(options.max_failover_retry_count, Some(5));
assert_eq!(options.max_session_retry_count, Some(3));
}
#[test]
fn view_resolves_across_layers() {
use std::sync::Arc;
let env = Arc::new(OperationOptions {
read_consistency_strategy: Some(ReadConsistencyStrategy::Eventual),
max_failover_retry_count: Some(3),
..Default::default()
});
let runtime = Arc::new(OperationOptions {
content_response_on_write: Some(ContentResponseOnWrite::Enabled),
..Default::default()
});
let account = Arc::new(OperationOptions {
max_failover_retry_count: Some(5),
content_response_on_write: Some(ContentResponseOnWrite::Disabled),
..Default::default()
});
let operation = OperationOptions {
read_consistency_strategy: Some(ReadConsistencyStrategy::Session),
..Default::default()
};
let view =
OperationOptionsView::new(Some(env), Some(runtime), Some(account), Some(&operation));
assert_eq!(
view.read_consistency_strategy(),
Some(&ReadConsistencyStrategy::Session)
);
assert_eq!(
view.content_response_on_write(),
Some(&ContentResponseOnWrite::Disabled)
);
assert_eq!(view.max_failover_retry_count(), Some(&5));
assert!(view.excluded_regions().is_none());
assert!(view.max_session_retry_count().is_none());
}
#[test]
fn from_env_vars_parses_known_vars() {
let options = OperationOptions::from_env_vars(|key| match key {
"AZURE_COSMOS_READ_CONSISTENCY_STRATEGY" => Ok("Session".to_string()),
"AZURE_COSMOS_CONTENT_RESPONSE_ON_WRITE" => Ok("true".to_string()),
"AZURE_COSMOS_MAX_FAILOVER_RETRY_COUNT" => Ok("7".to_string()),
"AZURE_COSMOS_MAX_SESSION_RETRY_COUNT" => Ok("3".to_string()),
_ => Err(std::env::VarError::NotPresent),
});
assert_eq!(
options.read_consistency_strategy,
Some(ReadConsistencyStrategy::Session)
);
assert_eq!(
options.content_response_on_write,
Some(ContentResponseOnWrite::Enabled)
);
assert_eq!(options.max_failover_retry_count, Some(7));
assert_eq!(options.max_session_retry_count, Some(3));
assert!(options.excluded_regions.is_none());
}
#[test]
fn from_env_vars_returns_none_for_missing_vars() {
let options = OperationOptions::from_env_vars(|_| Err(std::env::VarError::NotPresent));
assert!(options.read_consistency_strategy.is_none());
assert!(options.content_response_on_write.is_none());
assert!(options.excluded_regions.is_none());
assert!(options.max_failover_retry_count.is_none());
assert!(options.max_session_retry_count.is_none());
}
}