-
Notifications
You must be signed in to change notification settings - Fork 21
Open
Labels
ConfigsRelated to overall configuration of zainoRelated to overall configuration of zainotech-debtTechnical debt that needs to be addressedTechnical debt that needs to be addressedtype-safetyType safety improvementsType safety improvements
Description
Primitive Obsession - Configuration uses primitive types requiring runtime validation
Labels: configs
, tech-debt
, type-safety
Problem
The configuration system suffers from Primitive Obsession - using primitive types (strings, Option<usize>
) where domain-specific types would be safer and more expressive.
Current Problematic Code
// IndexerConfig
pub struct IndexerConfig {
pub network: String, // Runtime validation needed!
pub db_size: Option<usize>, // What does None mean? Unlimited? Unset?
pub map_shard_amount: Option<usize>, // Panics if not power of 2!
pub grpc_tls: bool, // Boolean blindness
pub tls_cert_path: Option<String>, // Must validate these together
pub tls_key_path: Option<String>,
// ...
}
// Runtime validation required
impl IndexerConfig {
pub fn check_config(&self) -> Result<(), IndexerError> {
// String comparison for network - error prone!
if (self.network != "Regtest") &&
(self.network != "Testnet") &&
(self.network != "Mainnet") {
return Err(IndexerError::ConfigError(
"Incorrect network name given...".to_string(),
));
}
// TLS validation - multiple fields must be checked together
if self.grpc_tls {
if self.tls_cert_path.is_none() {
return Err(IndexerError::ConfigError(
"TLS enabled but no cert path".to_string(),
));
}
// More validation...
}
}
}
// DashMap will panic at runtime!
// Documentation: "shard_amount should be power of two or function will panic"
pub map_shard_amount: Option<usize>,
Impact
- Runtime Errors: Invalid configs discovered only at runtime
- Poor UX: Users see panics instead of clear config errors
- Ambiguous Semantics:
None
can mean different things in different contexts - Validation Sprawl: Validation logic scattered throughout codebase
- Type Confusion: Easy to pass wrong string or number
Solution
Use domain-specific types that make invalid states unrepresentable:
// Network as enum - compile-time safety
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "lowercase")]
pub enum Network {
Mainnet,
Testnet,
Regtest,
}
// Explicit database size semantics
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub enum DatabaseSize {
Unlimited,
Gb(usize), // Clear units!
// Future: Mb(usize), Tb(usize)
}
// TLS config - impossible to have invalid state
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub enum TlsConfig {
Disabled,
Enabled {
cert_path: PathBuf, // Both required!
key_path: PathBuf,
},
}
// Power-of-two enforced at type level
pub struct CacheConfig {
pub capacity: usize,
pub shard_power: u8, // 2^shard_power shards - can't be invalid!
}
impl CacheConfig {
pub fn shard_count(&self) -> usize {
1 << self.shard_power // Always valid
}
}
Configuration becomes self-validating:
// No runtime validation needed!
pub struct IndexerConfig {
pub network: Network, // Can only be valid variant
pub database_size: DatabaseSize, // Clear semantics
pub tls: TlsConfig, // Impossible to have TLS enabled without paths
pub cache: Option<CacheConfig>, // None means "use defaults"
}
// TOML becomes clearer too:
// network = "mainnet" # Validated at parse time
// database_size = { gb = 10 } # Or "unlimited"
// tls = { enabled = { cert_path = "...", key_path = "..." }}
// cache = { capacity = 1000, shard_power = 4 } # 16 shards
Benefits:
- Parse-time validation instead of runtime
- Self-documenting configuration
- Impossible to create invalid states
- No runtime panics from bad config
- Better IDE autocomplete and documentation
nuttycom and ala-mode
Metadata
Metadata
Assignees
Labels
ConfigsRelated to overall configuration of zainoRelated to overall configuration of zainotech-debtTechnical debt that needs to be addressedTechnical debt that needs to be addressedtype-safetyType safety improvementsType safety improvements
Type
Projects
Status
In progress