Skip to main content

bucketwarden_server/
large_object_optimization_support.rs

1use super::*;
2
3pub const LARGE_OBJECT_MODE_MULTIPART: &str = "multipart-large-object";
4pub const LARGE_OBJECT_MODE_STRIPED: &str = "striped-large-object";
5pub const LARGE_OBJECT_MODE_PARALLEL_READ: &str = "parallel-read-large-object";
6pub const LARGE_OBJECT_MODE_PARALLEL_WRITE: &str = "parallel-write-large-object";
7
8pub const LARGE_OBJECT_MULTIPART_THRESHOLD_BYTES: usize = 5 * 1024 * 1024;
9
10const LARGE_OBJECT_CAPABILITIES: &[&str] = &[
11    "multipart-throughput",
12    "striping",
13    "parallel-reads",
14    "parallel-writes",
15    "range-read-behavior",
16    "native-support-state",
17    "semantic-parity",
18    "configuration-admin-surface",
19    "security-governance-impact",
20    "observability-evidence",
21    "failure-mode-behavior",
22    "validation-test-coverage",
23    "product-specific-caveats",
24];
25
26const LARGE_OBJECT_CAVEATS: &[&str] = &[
27    "BucketWarden supports multipart upload, part listing, multipart completion, copy-source ranges, HTTP range reads, integrity, encryption, audit, and notification semantics under the local runtime boundary.",
28    "Large-object multipart support is semantically validated, but no storage-engine throughput SLO or benchmark-backed numeric performance claim is made.",
29    "Striping, parallel read scheduling, and parallel write scheduling are tracked but fail closed until a durable scheduler and placement contract exist.",
30    "Large-object proof does not claim distributed striping, concurrent IO fanout, adaptive chunk sizing, or p95/p99 throughput targets.",
31];
32
33const LARGE_OBJECT_FAILURE_MODES: &[&str] = &[
34    "unsupported-large-object-mode-rejected",
35    "striped-large-object-mode-rejected",
36    "parallel-read-mode-rejected",
37    "parallel-write-mode-rejected",
38    "invalid-large-object-threshold-rejected",
39];
40
41#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
42pub struct LargeObjectOptimizationEntry {
43    pub mode: &'static str,
44    pub native_support: bool,
45    pub semantic_parity: &'static str,
46    pub storage_behavior: &'static str,
47    pub throughput_behavior: &'static str,
48    pub failure_mode: &'static str,
49    pub caveat: &'static str,
50}
51
52#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
53pub struct LargeObjectOptimizationReport {
54    pub active_mode: &'static str,
55    pub multipart_threshold_bytes: usize,
56    pub supported_modes: Vec<&'static str>,
57    pub unsupported_modes: Vec<&'static str>,
58    pub capabilities: Vec<&'static str>,
59    pub failure_modes: Vec<&'static str>,
60    pub caveats: Vec<&'static str>,
61    pub entries: Vec<LargeObjectOptimizationEntry>,
62}
63
64#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize)]
65pub struct LargeObjectOptimizationPolicy {
66    pub mode: String,
67    pub multipart_threshold_bytes: Option<usize>,
68    pub enable_striping: bool,
69    pub enable_parallel_reads: bool,
70    pub enable_parallel_writes: bool,
71    pub throughput_slo_bytes_per_second: Option<u64>,
72}
73
74impl BucketWarden {
75    pub fn large_object_optimization_report(&self) -> LargeObjectOptimizationReport {
76        LargeObjectOptimizationReport {
77            active_mode: LARGE_OBJECT_MODE_MULTIPART,
78            multipart_threshold_bytes: LARGE_OBJECT_MULTIPART_THRESHOLD_BYTES,
79            supported_modes: vec![LARGE_OBJECT_MODE_MULTIPART],
80            unsupported_modes: vec![
81                LARGE_OBJECT_MODE_STRIPED,
82                LARGE_OBJECT_MODE_PARALLEL_READ,
83                LARGE_OBJECT_MODE_PARALLEL_WRITE,
84            ],
85            capabilities: LARGE_OBJECT_CAPABILITIES.to_vec(),
86            failure_modes: LARGE_OBJECT_FAILURE_MODES.to_vec(),
87            caveats: LARGE_OBJECT_CAVEATS.to_vec(),
88            entries: vec![
89                LargeObjectOptimizationEntry {
90                    mode: LARGE_OBJECT_MODE_MULTIPART,
91                    native_support: true,
92                    semantic_parity: "Multipart uploads, ordered part completion, part checksums, version creation, encryption, lock defaults, audit, notifications, and range reads preserve the same object semantics as single PUT objects.",
93                    storage_behavior: "Completed multipart objects are stored as committed object versions with multipart integrity records.",
94                    throughput_behavior: "Multipart part ingestion and range reads are supported as protocol/runtime behavior; no benchmark-backed throughput SLO is claimed.",
95                    failure_mode: "Invalid threshold or unsupported optimization policy is rejected before claiming support.",
96                    caveat: "Multipart proof does not claim distributed striping or concurrent IO fanout.",
97                },
98                LargeObjectOptimizationEntry {
99                    mode: LARGE_OBJECT_MODE_STRIPED,
100                    native_support: false,
101                    semantic_parity: "No stripe placement, stripe index, or stripe recovery semantics are claimed.",
102                    storage_behavior: "Striped large-object storage is out of the current runtime boundary.",
103                    throughput_behavior: "Striping-related throughput improvement is not claimed.",
104                    failure_mode: "Striped large-object mode selection is rejected as unsupported.",
105                    caveat: "Striping needs durable placement, repair, recovery, and integrity contracts.",
106                },
107                LargeObjectOptimizationEntry {
108                    mode: LARGE_OBJECT_MODE_PARALLEL_READ,
109                    native_support: false,
110                    semantic_parity: "No parallel range scheduler or fanout read semantics are claimed.",
111                    storage_behavior: "Parallel read scheduling is out of the current runtime boundary.",
112                    throughput_behavior: "Parallel read throughput improvement is not claimed.",
113                    failure_mode: "Parallel read mode selection is rejected as unsupported.",
114                    caveat: "Parallel reads need scheduler, cancellation, ordering, and observability proof.",
115                },
116                LargeObjectOptimizationEntry {
117                    mode: LARGE_OBJECT_MODE_PARALLEL_WRITE,
118                    native_support: false,
119                    semantic_parity: "No parallel write scheduler or fanout write commit semantics are claimed.",
120                    storage_behavior: "Parallel write scheduling is out of the current runtime boundary.",
121                    throughput_behavior: "Parallel write throughput improvement is not claimed.",
122                    failure_mode: "Parallel write mode selection is rejected as unsupported.",
123                    caveat: "Parallel writes need atomic multi-part scheduling and failure recovery proof.",
124                },
125            ],
126        }
127    }
128
129    pub fn is_large_object(&self, body_len: usize) -> bool {
130        body_len >= LARGE_OBJECT_MULTIPART_THRESHOLD_BYTES
131    }
132
133    pub fn ensure_large_object_mode_supported(&self, mode: &str) -> Result<(), RuntimeError> {
134        let report = self.large_object_optimization_report();
135        if report.supported_modes.contains(&mode) {
136            Ok(())
137        } else {
138            Err(RuntimeError::UnsupportedLargeObjectOptimization(
139                mode.to_string(),
140            ))
141        }
142    }
143
144    pub fn validate_large_object_optimization_policy(
145        &self,
146        policy: &LargeObjectOptimizationPolicy,
147    ) -> Result<(), RuntimeError> {
148        self.ensure_large_object_mode_supported(&policy.mode)?;
149        if policy
150            .multipart_threshold_bytes
151            .is_some_and(|threshold| threshold == 0)
152        {
153            return Err(RuntimeError::InvalidLargeObjectOptimizationPolicy(
154                "large-object multipart threshold must be nonzero".to_string(),
155            ));
156        }
157        if policy.enable_striping {
158            return Err(RuntimeError::InvalidLargeObjectOptimizationPolicy(
159                "large-object striping is outside the current boundary".to_string(),
160            ));
161        }
162        if policy.enable_parallel_reads {
163            return Err(RuntimeError::InvalidLargeObjectOptimizationPolicy(
164                "parallel large-object reads are outside the current boundary".to_string(),
165            ));
166        }
167        if policy.enable_parallel_writes {
168            return Err(RuntimeError::InvalidLargeObjectOptimizationPolicy(
169                "parallel large-object writes are outside the current boundary".to_string(),
170            ));
171        }
172        if policy.throughput_slo_bytes_per_second.is_some() {
173            return Err(RuntimeError::InvalidLargeObjectOptimizationPolicy(
174                "numeric large-object throughput SLOs require benchmark evidence".to_string(),
175            ));
176        }
177        Ok(())
178    }
179}