use std::sync::LazyLock;
use tracing::warn;
pub(crate) const DEFAULT_MAX_STEPS: usize = 10_000;
pub(crate) const DEFAULT_MAX_CHAIN_SIZE: usize = 500;
pub(crate) const DEFAULT_MAX_HISTORICAL_PRICES: usize = 100_000;
pub(crate) const DEFAULT_EXPORT_BLOCK_ROWS: usize = 4_096;
pub(crate) static MAX_STEPS: LazyLock<usize> = LazyLock::new(|| {
parse_limit(
crate::utils::env::read_var("OCS_MAX_STEPS"),
DEFAULT_MAX_STEPS,
)
});
pub(crate) static MAX_CHAIN_SIZE: LazyLock<usize> = LazyLock::new(|| {
parse_limit(
crate::utils::env::read_var("OCS_MAX_CHAIN_SIZE"),
DEFAULT_MAX_CHAIN_SIZE,
)
});
pub(crate) const MAX_EXPORT_BLOCK_ROWS: usize = 262_144;
pub(crate) static EXPORT_BLOCK_ROWS: LazyLock<usize> = LazyLock::new(|| {
let configured = parse_limit(
crate::utils::env::read_var("OCS_EXPORT_BLOCK_ROWS"),
DEFAULT_EXPORT_BLOCK_ROWS,
);
if configured > MAX_EXPORT_BLOCK_ROWS {
warn!(
configured,
maximum = MAX_EXPORT_BLOCK_ROWS,
"OCS_EXPORT_BLOCK_ROWS above the maximum; using the maximum"
);
return MAX_EXPORT_BLOCK_ROWS;
}
configured
});
pub(crate) static MAX_HISTORICAL_PRICES: LazyLock<usize> = LazyLock::new(|| {
parse_limit(
crate::utils::env::read_var("OCS_MAX_HISTORICAL_PRICES"),
DEFAULT_MAX_HISTORICAL_PRICES,
)
});
#[must_use]
pub(crate) fn strikes_per_chain(chain_size: usize) -> Option<usize> {
chain_size.checked_mul(2)?.checked_add(1)
}
#[must_use]
pub(crate) fn parse_limit(raw: Option<String>, default: usize) -> usize {
match raw {
None => default,
Some(value) => match value.trim().parse::<usize>() {
Ok(parsed) if parsed >= 1 => parsed,
_ => {
warn!(
raw = %value,
default,
"invalid limit value; falling back to default"
);
default
}
},
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_limit_unset_uses_default() {
assert_eq!(parse_limit(None, 10), 10);
}
#[test]
fn test_parse_limit_valid_value_is_used() {
assert_eq!(parse_limit(Some("42".to_string()), 10), 42);
}
#[test]
fn test_parse_limit_trims_whitespace() {
assert_eq!(parse_limit(Some(" 25 ".to_string()), 10), 25);
}
#[test]
fn test_parse_limit_non_numeric_falls_back() {
assert_eq!(parse_limit(Some("not-a-number".to_string()), 10), 10);
}
#[test]
fn test_parse_limit_zero_falls_back() {
assert_eq!(parse_limit(Some("0".to_string()), 10), 10);
}
#[test]
fn test_parse_limit_negative_falls_back() {
assert_eq!(parse_limit(Some("-5".to_string()), 10), 10);
}
#[test]
fn test_default_limits_match_documentation() {
assert_eq!(*MAX_STEPS, DEFAULT_MAX_STEPS);
assert_eq!(*MAX_STEPS, 10_000);
assert_eq!(*MAX_CHAIN_SIZE, DEFAULT_MAX_CHAIN_SIZE);
assert_eq!(*MAX_CHAIN_SIZE, 500);
assert_eq!(*MAX_HISTORICAL_PRICES, DEFAULT_MAX_HISTORICAL_PRICES);
assert_eq!(*MAX_HISTORICAL_PRICES, 100_000);
assert_eq!(*EXPORT_BLOCK_ROWS, DEFAULT_EXPORT_BLOCK_ROWS);
assert_eq!(*EXPORT_BLOCK_ROWS, 4_096);
assert_eq!(MAX_EXPORT_BLOCK_ROWS, 262_144);
}
}