Repository: tikv/tikv
File: src/config/mod.rs (Rust)

Code before:
                "the max_flush_interval is too small, it is {}, and should be greater than 10s.",
                self.max_flush_interval
            )
            .into());
        }
        if self.min_ts_interval < ReadableDuration::secs(1) {
            return Err(format!(
                "the min_ts_interval is too small, it is {}, and should be greater than 1s.",
                self.min_ts_interval
            )
            .into());
        }
        if self.initial_scan_concurrency == 0 {
            return Err("the `initial_scan_concurrency` shouldn't be zero".into());
        }
        if self.initial_scan_rate_limit.0 < 1024 {
            return Err("the `initial_scan_rate_limit` should be at least 1024 bytes".into());
        }
        Ok(())
    }
}

impl Default for BackupStreamConfig {
    fn default() -> Self {
        let cpu_num = SysQuota::cpu_cores_quota();
        let total_mem = SysQuota::memory_limit_in_bytes();
        let file_size_limit = ReadableSize::mb(256);
        // Don't use too many memory.
        let temp_file_quota = total_mem / 16;
        let quota_size = (total_mem as f64 * 0.1).min(ReadableSize::mb(512).0 as _);
        // 2x of the max pending bytes. The extra buffer make us easier to keep all
        // files in memory.
        let preferred_cache_size = file_size_limit.0 * 2;
        let cache_size = ReadableSize(temp_file_quota.min(preferred_cache_size));
        Self {
            min_ts_interval: ReadableDuration::secs(10),
            max_flush_interval: ReadableDuration::minutes(3),
            // use at most 50% of vCPU by default
            num_threads: (cpu_num * 0.5).clamp(2.0, 12.0) as usize,
            enable: true,
            // TODO: may be use raft store directory
            temp_path: String::new(),
            file_size_limit,
            initial_scan_pending_memory_quota: ReadableSize(quota_size as _),
            initial_scan_rate_limit: ReadableSize::mb(60),
            initial_scan_concurrency: 6,
            temp_file_memory_quota: cache_size,
        }
    }
}


Review comment (suggestion):
The validation is missing a minimum size check. AWS S3 requires each part to be at least 5 MiB (MINIMUM_PART_SIZE). While set_multi_part_size in S3Storage clamps values below 5MB to the minimum, it would be better to validate this in the configuration layer to provide clear feedback to users. Consider adding a check like: if self.s3_multi_part_size.0 > 0 && self.s3_multi_part_size.0 < ReadableSize::mb(5).0 to ensure the configured value meets S3's requirements.

Code after:
            return Err(format!(
                "the max_flush_interval is too small, it is {}, and should be greater than 10s.",
                self.max_flush_interval
            )
            .into());
        }
        if self.min_ts_interval < ReadableDuration::secs(1) {
            return Err(format!(
                "the min_ts_interval is too small, it is {}, and should be greater than 1s.",
                self.min_ts_interval
            )
            .into());
        }
        if self.initial_scan_concurrency == 0 {
            return Err("the `initial_scan_concurrency` shouldn't be zero".into());
        }
        if self.initial_scan_rate_limit.0 < 1024 {
            return Err("the `initial_scan_rate_limit` should be at least 1024 bytes".into());
        }
        if self.s3_multi_part_size.0 > ReadableSize::gb(5).0 {
            warn!(
                "backup.s3_multi_part_size cannot larger than 5GB, change it to {:?}",
                default_cfg.s3_multi_part_size
            );
            self.s3_multi_part_size = default_cfg.s3_multi_part_size;
        }

        Ok(())
    }
}

impl Default for BackupStreamConfig {
    fn default() -> Self {
        let cpu_num = SysQuota::cpu_cores_quota();
        let total_mem = SysQuota::memory_limit_in_bytes();
        let file_size_limit = ReadableSize::mb(256);
        // Don't use too many memory.
        let temp_file_quota = total_mem / 16;
        let quota_size = (total_mem as f64 * 0.1).min(ReadableSize::mb(512).0 as _);
        // 2x of the max pending bytes. The extra buffer make us easier to keep all
        // files in memory.
        let preferred_cache_size = file_size_limit.0 * 2;
        let cache_size = ReadableSize(temp_file_quota.min(preferred_cache_size));
        Self {
            min_ts_interval: ReadableDuration::secs(10),
            max_flush_interval: ReadableDuration::minutes(3),
            // use at most 50% of vCPU by default
            num_threads: (cpu_num * 0.5).clamp(2.0, 12.0) as usize,
            enable: true,
            // TODO: may be use raft store directory
            temp_path: String::new(),