laminar_db/config.rs
1//! Configuration for `LaminarDB`.
2#![allow(clippy::disallowed_types)] // cold path
3
4use std::collections::HashMap;
5use std::path::PathBuf;
6
7use laminar_core::streaming::{BackpressureStrategy, StreamCheckpointConfig};
8
9/// SQL identifier case sensitivity mode.
10///
11/// Controls how unquoted SQL identifiers are matched against Arrow
12/// schema field names.
13///
14/// `LaminarDB` defaults to [`CaseSensitive`](IdentifierCaseSensitivity::CaseSensitive)
15/// (normalization disabled) so that mixed-case column names from
16/// external sources (Kafka, CDC, `WebSocket`) work without double-quoting.
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
18pub enum IdentifierCaseSensitivity {
19 /// Preserve case as-written, case-sensitive matching (default).
20 ///
21 /// `SELECT tradeId` matches only `tradeId` in the schema.
22 /// This is the recommended mode for financial / `IoT` data sources
23 /// that use `camelCase` or `PascalCase` field names.
24 #[default]
25 CaseSensitive,
26 /// Normalize unquoted identifiers to lowercase (standard SQL behaviour).
27 ///
28 /// `SELECT TradeId` becomes `SELECT tradeid` before schema matching.
29 /// Use this if all your schemas use lowercase column names.
30 Lowercase,
31}
32
33/// S3 storage class tiering configuration.
34///
35/// Controls how checkpoint objects are assigned to S3 storage classes
36/// for cost optimization. Active checkpoints use the hot tier (fast access),
37/// older checkpoints are moved to warm/cold tiers via S3 Lifecycle rules.
38#[derive(Debug, Clone, PartialEq, Eq)]
39pub struct TieringConfig {
40 /// Storage class for active checkpoints (e.g., `"EXPRESS_ONE_ZONE"`, `"STANDARD"`).
41 pub hot_class: String,
42 /// Storage class for older checkpoints (e.g., `"STANDARD"`).
43 pub warm_class: String,
44 /// Storage class for archive checkpoints (e.g., `"GLACIER_IR"`). Empty = no cold tier.
45 pub cold_class: String,
46 /// Time before moving objects from hot to warm tier (seconds).
47 pub hot_retention_secs: u64,
48 /// Time before moving objects from warm to cold tier (seconds). 0 = no cold tier.
49 pub warm_retention_secs: u64,
50}
51
52impl Default for TieringConfig {
53 fn default() -> Self {
54 Self {
55 hot_class: "STANDARD".to_string(),
56 warm_class: "STANDARD".to_string(),
57 cold_class: String::new(),
58 hot_retention_secs: 86400, // 24h
59 warm_retention_secs: 604_800, // 7d
60 }
61 }
62}
63
64/// Thread-per-core runtime configuration.
65///
66/// Controls CPU pinning, core count, and NUMA settings for the TPC
67/// pipeline. When `None` on [`LaminarConfig`], auto-detected defaults
68/// are used.
69#[derive(Debug, Clone)]
70pub struct TpcRuntimeConfig {
71 /// Number of cores (`None` = auto-detect via `available_parallelism`).
72 pub num_cores: Option<usize>,
73 /// Pin core threads to CPUs starting from `cpu_start`.
74 pub cpu_pinning: bool,
75 /// First CPU ID for pinning.
76 pub cpu_start: usize,
77 /// Enable NUMA-aware memory allocation.
78 pub numa_aware: bool,
79}
80
81impl TpcRuntimeConfig {
82 /// Auto-detect system capabilities.
83 #[must_use]
84 pub fn auto() -> Self {
85 Self {
86 num_cores: None,
87 cpu_pinning: cfg!(target_os = "linux"),
88 cpu_start: 0,
89 numa_aware: cfg!(target_os = "linux"),
90 }
91 }
92}
93
94impl Default for TpcRuntimeConfig {
95 fn default() -> Self {
96 Self::auto()
97 }
98}
99
100/// Configuration for a `LaminarDB` instance.
101#[derive(Debug, Clone)]
102pub struct LaminarConfig {
103 /// Default buffer size for streaming channels.
104 pub default_buffer_size: usize,
105 /// Default backpressure strategy.
106 pub default_backpressure: BackpressureStrategy,
107 /// Storage directory for WAL and checkpoints (`None` = in-memory only).
108 pub storage_dir: Option<PathBuf>,
109 /// Streaming checkpoint configuration (`None` = disabled).
110 pub checkpoint: Option<StreamCheckpointConfig>,
111 /// SQL identifier case sensitivity mode.
112 pub identifier_case: IdentifierCaseSensitivity,
113 /// Object store URL for cloud checkpoint storage (e.g., `s3://bucket/prefix`).
114 pub object_store_url: Option<String>,
115 /// Explicit credential/config overrides for the object store builder.
116 pub object_store_options: HashMap<String, String>,
117 /// S3 storage class tiering configuration (`None` = use default STANDARD).
118 pub tiering: Option<TieringConfig>,
119 /// Thread-per-core runtime configuration (`None` = use tokio mode).
120 pub tpc: Option<TpcRuntimeConfig>,
121}
122
123impl Default for LaminarConfig {
124 fn default() -> Self {
125 Self {
126 default_buffer_size: 65536,
127 default_backpressure: BackpressureStrategy::Block,
128 storage_dir: None,
129 checkpoint: None,
130 identifier_case: IdentifierCaseSensitivity::default(),
131 object_store_url: None,
132 object_store_options: HashMap::new(),
133 tiering: None,
134 tpc: None,
135 }
136 }
137}