use crate::ClientError;
use crate::ClientResult;
pub struct ProducerConfigValidator;
impl ProducerConfigValidator {
pub const MIN_SEND_MSG_TIMEOUT: u32 = 100;
pub const MAX_SEND_MSG_TIMEOUT: u32 = 300_000;
pub const MIN_MAX_MESSAGE_SIZE: u32 = 1024;
pub const MAX_MAX_MESSAGE_SIZE: u32 = 128 * 1024 * 1024;
pub const MIN_DEFAULT_TOPIC_QUEUE_NUMS: u32 = 1;
pub const MAX_DEFAULT_TOPIC_QUEUE_NUMS: u32 = 1024;
pub const MIN_RETRY_TIMES: u32 = 0;
pub const MAX_RETRY_TIMES: u32 = 16;
pub const MIN_COMPRESS_MSG_BODY_OVER_HOWMUCH: u32 = 1024;
pub const MAX_COMPRESS_MSG_BODY_OVER_HOWMUCH: u32 = 64 * 1024 * 1024;
pub const MIN_BATCH_MAX_DELAY_MS: u32 = 0;
pub const MAX_BATCH_MAX_DELAY_MS: u32 = 60_000;
pub const MIN_BACK_PRESSURE_FOR_ASYNC_SEND_NUM: u32 = 10;
pub const MAX_BACK_PRESSURE_FOR_ASYNC_SEND_NUM: u32 = 100_000;
pub const MIN_BACK_PRESSURE_FOR_ASYNC_SEND_SIZE: u32 = 1024 * 1024;
pub const MAX_BACK_PRESSURE_FOR_ASYNC_SEND_SIZE: u32 = 1024 * 1024 * 1024;
pub fn validate_send_msg_timeout(timeout: u32) -> ClientResult<()> {
if !(Self::MIN_SEND_MSG_TIMEOUT..=Self::MAX_SEND_MSG_TIMEOUT).contains(&timeout) {
return Err(ClientError::config_invalid(
"send_msg_timeout",
timeout.to_string(),
format!(
"must be between {} and {} milliseconds",
Self::MIN_SEND_MSG_TIMEOUT,
Self::MAX_SEND_MSG_TIMEOUT
),
));
}
Ok(())
}
pub fn validate_send_msg_max_timeout_per_request(timeout: Option<u32>) -> ClientResult<()> {
if let Some(t) = timeout {
if !(Self::MIN_SEND_MSG_TIMEOUT..=Self::MAX_SEND_MSG_TIMEOUT).contains(&t) {
return Err(ClientError::config_invalid(
"send_msg_max_timeout_per_request",
t.to_string(),
format!(
"must be between {} and {} milliseconds, or None for no limit",
Self::MIN_SEND_MSG_TIMEOUT,
Self::MAX_SEND_MSG_TIMEOUT
),
));
}
}
Ok(())
}
pub fn validate_max_message_size(size: u32) -> ClientResult<()> {
if !(Self::MIN_MAX_MESSAGE_SIZE..=Self::MAX_MAX_MESSAGE_SIZE).contains(&size) {
return Err(ClientError::config_invalid(
"max_message_size",
size.to_string(),
format!(
"must be between {} and {} bytes",
Self::MIN_MAX_MESSAGE_SIZE,
Self::MAX_MAX_MESSAGE_SIZE
),
));
}
Ok(())
}
pub fn validate_default_topic_queue_nums(nums: u32) -> ClientResult<()> {
if !(Self::MIN_DEFAULT_TOPIC_QUEUE_NUMS..=Self::MAX_DEFAULT_TOPIC_QUEUE_NUMS).contains(&nums) {
return Err(ClientError::config_invalid(
"default_topic_queue_nums",
nums.to_string(),
format!(
"must be between {} and {}",
Self::MIN_DEFAULT_TOPIC_QUEUE_NUMS,
Self::MAX_DEFAULT_TOPIC_QUEUE_NUMS
),
));
}
Ok(())
}
pub fn validate_retry_times_when_send_failed(times: u32) -> ClientResult<()> {
if times > Self::MAX_RETRY_TIMES {
return Err(ClientError::config_invalid(
"retry_times_when_send_failed",
times.to_string(),
format!("must not exceed {}", Self::MAX_RETRY_TIMES),
));
}
Ok(())
}
pub fn validate_retry_times_when_send_async_failed(times: u32) -> ClientResult<()> {
if times > Self::MAX_RETRY_TIMES {
return Err(ClientError::config_invalid(
"retry_times_when_send_async_failed",
times.to_string(),
format!("must not exceed {}", Self::MAX_RETRY_TIMES),
));
}
Ok(())
}
pub fn validate_compress_msg_body_over_howmuch(threshold: u32) -> ClientResult<()> {
if !(Self::MIN_COMPRESS_MSG_BODY_OVER_HOWMUCH..=Self::MAX_COMPRESS_MSG_BODY_OVER_HOWMUCH).contains(&threshold) {
return Err(ClientError::config_invalid(
"compress_msg_body_over_howmuch",
threshold.to_string(),
format!(
"must be between {} and {} bytes",
Self::MIN_COMPRESS_MSG_BODY_OVER_HOWMUCH,
Self::MAX_COMPRESS_MSG_BODY_OVER_HOWMUCH
),
));
}
Ok(())
}
pub fn validate_batch_max_delay_ms(delay: Option<u32>) -> ClientResult<()> {
if let Some(d) = delay {
if d > Self::MAX_BATCH_MAX_DELAY_MS {
return Err(ClientError::config_invalid(
"batch_max_delay_ms",
d.to_string(),
format!(
"must be at most {} milliseconds, or None for no delay",
Self::MAX_BATCH_MAX_DELAY_MS
),
));
}
}
Ok(())
}
pub fn validate_back_pressure_for_async_send_num(num: u32) -> ClientResult<()> {
if !(Self::MIN_BACK_PRESSURE_FOR_ASYNC_SEND_NUM..=Self::MAX_BACK_PRESSURE_FOR_ASYNC_SEND_NUM).contains(&num) {
return Err(ClientError::config_invalid(
"back_pressure_for_async_send_num",
num.to_string(),
format!(
"must be between {} and {}",
Self::MIN_BACK_PRESSURE_FOR_ASYNC_SEND_NUM,
Self::MAX_BACK_PRESSURE_FOR_ASYNC_SEND_NUM
),
));
}
Ok(())
}
pub fn validate_back_pressure_for_async_send_size(size: u32) -> ClientResult<()> {
if !(Self::MIN_BACK_PRESSURE_FOR_ASYNC_SEND_SIZE..=Self::MAX_BACK_PRESSURE_FOR_ASYNC_SEND_SIZE).contains(&size)
{
return Err(ClientError::config_invalid(
"back_pressure_for_async_send_size",
size.to_string(),
format!(
"must be between {} and {} bytes",
Self::MIN_BACK_PRESSURE_FOR_ASYNC_SEND_SIZE,
Self::MAX_BACK_PRESSURE_FOR_ASYNC_SEND_SIZE
),
));
}
Ok(())
}
pub fn validate_batch_max_bytes(size: Option<u64>) -> ClientResult<()> {
const MIN_BATCH_MAX_BYTES: u64 = 1024; const MAX_BATCH_MAX_BYTES: u64 = 32 * 1024 * 1024;
if let Some(s) = size {
if !(MIN_BATCH_MAX_BYTES..=MAX_BATCH_MAX_BYTES).contains(&s) {
return Err(ClientError::config_invalid(
"batch_max_bytes",
s.to_string(),
format!(
"must be between {} and {} bytes, or None for no limit",
MIN_BATCH_MAX_BYTES, MAX_BATCH_MAX_BYTES
),
));
}
}
Ok(())
}
pub fn validate_total_batch_max_bytes(size: Option<u64>) -> ClientResult<()> {
const MIN_TOTAL_BATCH_MAX_BYTES: u64 = 1024; const MAX_TOTAL_BATCH_MAX_BYTES: u64 = 256 * 1024 * 1024;
if let Some(s) = size {
if !(MIN_TOTAL_BATCH_MAX_BYTES..=MAX_TOTAL_BATCH_MAX_BYTES).contains(&s) {
return Err(ClientError::config_invalid(
"total_batch_max_bytes",
s.to_string(),
format!(
"must be between {} and {} bytes, or None for no limit",
MIN_TOTAL_BATCH_MAX_BYTES, MAX_TOTAL_BATCH_MAX_BYTES
),
));
}
}
Ok(())
}
pub fn validate_producer_group(group: &str) -> ClientResult<()> {
if group.is_empty() {
return Err(ClientError::config_missing("producer_group"));
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_validate_send_msg_timeout_valid() {
assert!(ProducerConfigValidator::validate_send_msg_timeout(3000).is_ok());
assert!(ProducerConfigValidator::validate_send_msg_timeout(100).is_ok());
assert!(ProducerConfigValidator::validate_send_msg_timeout(300_000).is_ok());
}
#[test]
fn test_validate_send_msg_timeout_invalid() {
assert!(ProducerConfigValidator::validate_send_msg_timeout(10).is_err());
assert!(ProducerConfigValidator::validate_send_msg_timeout(400_000).is_err());
}
#[test]
fn test_validate_send_msg_max_timeout_per_request_none() {
assert!(ProducerConfigValidator::validate_send_msg_max_timeout_per_request(None).is_ok());
}
#[test]
fn test_validate_send_msg_max_timeout_per_request_valid() {
assert!(ProducerConfigValidator::validate_send_msg_max_timeout_per_request(Some(3000)).is_ok());
}
#[test]
fn test_validate_send_msg_max_timeout_per_request_invalid() {
assert!(ProducerConfigValidator::validate_send_msg_max_timeout_per_request(Some(10)).is_err());
}
#[test]
fn test_validate_max_message_size_valid() {
assert!(ProducerConfigValidator::validate_max_message_size(4 * 1024 * 1024).is_ok());
assert!(ProducerConfigValidator::validate_max_message_size(1024).is_ok());
assert!(ProducerConfigValidator::validate_max_message_size(128 * 1024 * 1024).is_ok());
}
#[test]
fn test_validate_max_message_size_invalid() {
assert!(ProducerConfigValidator::validate_max_message_size(512).is_err());
assert!(ProducerConfigValidator::validate_max_message_size(256 * 1024 * 1024).is_err());
}
#[test]
fn test_validate_retry_times_when_send_failed_valid() {
assert!(ProducerConfigValidator::validate_retry_times_when_send_failed(0).is_ok());
assert!(ProducerConfigValidator::validate_retry_times_when_send_failed(2).is_ok());
assert!(ProducerConfigValidator::validate_retry_times_when_send_failed(16).is_ok());
}
#[test]
fn test_validate_retry_times_when_send_failed_invalid() {
assert!(ProducerConfigValidator::validate_retry_times_when_send_failed(17).is_err());
}
#[test]
fn test_validate_back_pressure_for_async_send_num_valid() {
assert!(ProducerConfigValidator::validate_back_pressure_for_async_send_num(1024).is_ok());
assert!(ProducerConfigValidator::validate_back_pressure_for_async_send_num(10).is_ok());
}
#[test]
fn test_validate_back_pressure_for_async_send_num_invalid() {
assert!(ProducerConfigValidator::validate_back_pressure_for_async_send_num(9).is_err());
assert!(ProducerConfigValidator::validate_back_pressure_for_async_send_num(100_001).is_err());
}
#[test]
fn test_validate_producer_group_empty() {
assert!(ProducerConfigValidator::validate_producer_group("").is_err());
}
#[test]
fn test_validate_producer_group_valid() {
assert!(ProducerConfigValidator::validate_producer_group("test_group").is_ok());
}
#[test]
fn test_validate_batch_max_delay_ms_none() {
assert!(ProducerConfigValidator::validate_batch_max_delay_ms(None).is_ok());
}
#[test]
fn test_validate_batch_max_delay_ms_valid() {
assert!(ProducerConfigValidator::validate_batch_max_delay_ms(Some(1000)).is_ok());
}
#[test]
fn test_validate_batch_max_delay_ms_invalid() {
assert!(ProducerConfigValidator::validate_batch_max_delay_ms(Some(70_000)).is_err());
}
#[test]
fn test_validate_batch_max_bytes_none() {
assert!(ProducerConfigValidator::validate_batch_max_bytes(None).is_ok());
}
#[test]
fn test_validate_batch_max_bytes_valid() {
assert!(ProducerConfigValidator::validate_batch_max_bytes(Some(1024)).is_ok());
assert!(ProducerConfigValidator::validate_batch_max_bytes(Some(4 * 1024 * 1024)).is_ok());
assert!(ProducerConfigValidator::validate_batch_max_bytes(Some(32 * 1024 * 1024)).is_ok());
}
#[test]
fn test_validate_batch_max_bytes_invalid() {
assert!(ProducerConfigValidator::validate_batch_max_bytes(Some(512)).is_err());
assert!(ProducerConfigValidator::validate_batch_max_bytes(Some(64 * 1024 * 1024)).is_err());
}
#[test]
fn test_validate_total_batch_max_bytes_none() {
assert!(ProducerConfigValidator::validate_total_batch_max_bytes(None).is_ok());
}
#[test]
fn test_validate_total_batch_max_bytes_valid() {
assert!(ProducerConfigValidator::validate_total_batch_max_bytes(Some(1024)).is_ok());
assert!(ProducerConfigValidator::validate_total_batch_max_bytes(Some(64 * 1024 * 1024)).is_ok());
assert!(ProducerConfigValidator::validate_total_batch_max_bytes(Some(256 * 1024 * 1024)).is_ok());
}
#[test]
fn test_validate_total_batch_max_bytes_invalid() {
assert!(ProducerConfigValidator::validate_total_batch_max_bytes(Some(512)).is_err());
assert!(ProducerConfigValidator::validate_total_batch_max_bytes(Some(512 * 1024 * 1024)).is_err());
}
}