Skip to main content

formualizer_eval/engine/
formula_ingest.rs

1use std::collections::BTreeMap;
2use std::sync::Arc;
3
4use super::FormulaPlaneMode;
5use super::arena::AstNodeId;
6use super::formula_source::{SourceFamilyId, SourceFormulaOrder};
7
8#[derive(Clone, Debug)]
9pub struct FormulaIngestRecord {
10    pub row: u32,
11    pub col: u32,
12    pub ast_id: AstNodeId,
13    pub formula_text: Option<Arc<str>>,
14    pub(crate) source_order: Option<SourceFormulaOrder>,
15    pub(crate) source_family: Option<SourceFamilyId>,
16    pub(crate) partition_owner: Option<SourceFamilyId>,
17}
18
19impl FormulaIngestRecord {
20    pub fn new(row: u32, col: u32, ast_id: AstNodeId, formula_text: Option<Arc<str>>) -> Self {
21        Self {
22            row,
23            col,
24            ast_id,
25            formula_text,
26            source_order: None,
27            source_family: None,
28            partition_owner: None,
29        }
30    }
31
32    pub(crate) fn with_source_proof(
33        mut self,
34        source_order: SourceFormulaOrder,
35        source_family: Option<SourceFamilyId>,
36        partition_owner: Option<SourceFamilyId>,
37    ) -> Self {
38        self.source_order = Some(source_order);
39        self.source_family = source_family;
40        self.partition_owner = partition_owner;
41        self
42    }
43}
44
45#[derive(Clone, Debug)]
46pub struct FormulaIngestBatch {
47    pub sheet_name: String,
48    pub formulas: Vec<FormulaIngestRecord>,
49}
50
51impl FormulaIngestBatch {
52    pub fn new(sheet_name: impl Into<String>, formulas: Vec<FormulaIngestRecord>) -> Self {
53        Self {
54            sheet_name: sheet_name.into(),
55            formulas,
56        }
57    }
58
59    pub fn len(&self) -> usize {
60        self.formulas.len()
61    }
62
63    pub fn is_empty(&self) -> bool {
64        self.formulas.is_empty()
65    }
66}
67
68#[derive(Debug, Clone, PartialEq, Eq)]
69pub struct FormulaIngestReport {
70    pub mode: FormulaPlaneMode,
71    pub formula_cells_seen: u64,
72    pub graph_formula_cells_materialized: u64,
73
74    pub shadow_candidate_cells: u64,
75    pub shadow_accepted_span_cells: u64,
76    pub shadow_fallback_cells: u64,
77    pub shadow_templates_interned: u64,
78    pub shadow_spans_created: u64,
79
80    pub graph_formula_vertices_avoided_shadow: u64,
81    pub ast_roots_avoided_shadow: u64,
82    pub edge_rows_avoided_shadow: u64,
83
84    pub graph_vertices_created: u64,
85    pub graph_edges_created: u64,
86
87    pub source_formula_events: u64,
88    pub source_formula_records_spooled: u64,
89    pub source_spool_encoded_bytes: u64,
90    pub source_spool_peak_memory_bytes: u64,
91    pub source_spool_spilled_bytes: u64,
92    pub source_spool_spill_files: u64,
93    pub source_spool_replays: u64,
94    pub source_ordinary_events: u64,
95    pub source_shared_anchor_events: u64,
96    pub source_shared_descendant_events: u64,
97    pub source_unknown_events: u64,
98    pub source_families_seen: u64,
99    pub source_family_cells_seen: u64,
100    pub source_family_shadow_eligible: u64,
101    pub source_family_shadow_eligible_cells: u64,
102    pub source_family_promoted: u64,
103    pub source_family_promoted_cells: u64,
104    pub source_family_fallback: u64,
105    pub source_family_fallback_cells: u64,
106    pub source_forward_descendants: u64,
107    pub source_evidence_limit_fallbacks: u64,
108    pub source_evidence_peak_bytes: u64,
109    pub source_anchor_parses: u64,
110    pub source_anchor_asts: u64,
111    pub source_anchor_analyses: u64,
112    pub source_descendant_strings_avoided: u64,
113    pub source_descendant_events_avoided: u64,
114    pub source_descendant_analyses_avoided: u64,
115    pub source_compressed_families_prepared: u64,
116    pub source_compressed_cells_prepared: u64,
117    pub source_partitioned_families_seen: u64,
118    pub source_partitioned_families_prepared: u64,
119    pub source_partitioned_families_rejected: u64,
120    pub source_partition_fragments_prepared: u64,
121    pub source_partition_span_cells_prepared: u64,
122    pub source_partition_fallback_cells: u64,
123    pub source_partition_analyses_reused: u64,
124    pub source_partition_function_semantics: u64,
125    pub source_partition_holes: u64,
126    pub source_partition_ordinary_exceptions: u64,
127    pub source_partition_failures: u64,
128    pub source_partition_surviving_cells: u64,
129
130    pub fallback_reasons: BTreeMap<String, u64>,
131}
132
133impl Default for FormulaIngestReport {
134    fn default() -> Self {
135        Self {
136            mode: FormulaPlaneMode::Off,
137            formula_cells_seen: 0,
138            graph_formula_cells_materialized: 0,
139            shadow_candidate_cells: 0,
140            shadow_accepted_span_cells: 0,
141            shadow_fallback_cells: 0,
142            shadow_templates_interned: 0,
143            shadow_spans_created: 0,
144            graph_formula_vertices_avoided_shadow: 0,
145            ast_roots_avoided_shadow: 0,
146            edge_rows_avoided_shadow: 0,
147            graph_vertices_created: 0,
148            graph_edges_created: 0,
149            source_formula_events: 0,
150            source_formula_records_spooled: 0,
151            source_spool_encoded_bytes: 0,
152            source_spool_peak_memory_bytes: 0,
153            source_spool_spilled_bytes: 0,
154            source_spool_spill_files: 0,
155            source_spool_replays: 0,
156            source_ordinary_events: 0,
157            source_shared_anchor_events: 0,
158            source_shared_descendant_events: 0,
159            source_unknown_events: 0,
160            source_families_seen: 0,
161            source_family_cells_seen: 0,
162            source_family_shadow_eligible: 0,
163            source_family_shadow_eligible_cells: 0,
164            source_family_promoted: 0,
165            source_family_promoted_cells: 0,
166            source_family_fallback: 0,
167            source_family_fallback_cells: 0,
168            source_forward_descendants: 0,
169            source_evidence_limit_fallbacks: 0,
170            source_evidence_peak_bytes: 0,
171            source_anchor_parses: 0,
172            source_anchor_asts: 0,
173            source_anchor_analyses: 0,
174            source_descendant_strings_avoided: 0,
175            source_descendant_events_avoided: 0,
176            source_descendant_analyses_avoided: 0,
177            source_compressed_families_prepared: 0,
178            source_compressed_cells_prepared: 0,
179            source_partitioned_families_seen: 0,
180            source_partitioned_families_prepared: 0,
181            source_partitioned_families_rejected: 0,
182            source_partition_fragments_prepared: 0,
183            source_partition_span_cells_prepared: 0,
184            source_partition_fallback_cells: 0,
185            source_partition_analyses_reused: 0,
186            source_partition_function_semantics: 0,
187            source_partition_holes: 0,
188            source_partition_ordinary_exceptions: 0,
189            source_partition_failures: 0,
190            source_partition_surviving_cells: 0,
191            fallback_reasons: BTreeMap::new(),
192        }
193    }
194}
195
196impl FormulaIngestReport {
197    pub(crate) fn with_mode(mode: FormulaPlaneMode) -> Self {
198        Self {
199            mode,
200            ..Self::default()
201        }
202    }
203
204    pub(crate) fn accumulate(&mut self, other: &Self) {
205        self.formula_cells_seen = self
206            .formula_cells_seen
207            .saturating_add(other.formula_cells_seen);
208        self.graph_formula_cells_materialized = self
209            .graph_formula_cells_materialized
210            .saturating_add(other.graph_formula_cells_materialized);
211        self.shadow_candidate_cells = self
212            .shadow_candidate_cells
213            .saturating_add(other.shadow_candidate_cells);
214        self.shadow_accepted_span_cells = self
215            .shadow_accepted_span_cells
216            .saturating_add(other.shadow_accepted_span_cells);
217        self.shadow_fallback_cells = self
218            .shadow_fallback_cells
219            .saturating_add(other.shadow_fallback_cells);
220        self.shadow_templates_interned = self
221            .shadow_templates_interned
222            .saturating_add(other.shadow_templates_interned);
223        self.shadow_spans_created = self
224            .shadow_spans_created
225            .saturating_add(other.shadow_spans_created);
226        self.graph_formula_vertices_avoided_shadow = self
227            .graph_formula_vertices_avoided_shadow
228            .saturating_add(other.graph_formula_vertices_avoided_shadow);
229        self.ast_roots_avoided_shadow = self
230            .ast_roots_avoided_shadow
231            .saturating_add(other.ast_roots_avoided_shadow);
232        self.edge_rows_avoided_shadow = self
233            .edge_rows_avoided_shadow
234            .saturating_add(other.edge_rows_avoided_shadow);
235        self.graph_vertices_created = self
236            .graph_vertices_created
237            .saturating_add(other.graph_vertices_created);
238        self.graph_edges_created = self
239            .graph_edges_created
240            .saturating_add(other.graph_edges_created);
241        self.source_formula_events = self
242            .source_formula_events
243            .saturating_add(other.source_formula_events);
244        self.source_formula_records_spooled = self
245            .source_formula_records_spooled
246            .saturating_add(other.source_formula_records_spooled);
247        self.source_spool_encoded_bytes = self
248            .source_spool_encoded_bytes
249            .saturating_add(other.source_spool_encoded_bytes);
250        self.source_spool_peak_memory_bytes = self
251            .source_spool_peak_memory_bytes
252            .max(other.source_spool_peak_memory_bytes);
253        self.source_spool_spilled_bytes = self
254            .source_spool_spilled_bytes
255            .saturating_add(other.source_spool_spilled_bytes);
256        self.source_spool_spill_files = self
257            .source_spool_spill_files
258            .saturating_add(other.source_spool_spill_files);
259        self.source_spool_replays = self
260            .source_spool_replays
261            .saturating_add(other.source_spool_replays);
262        self.source_ordinary_events = self
263            .source_ordinary_events
264            .saturating_add(other.source_ordinary_events);
265        self.source_shared_anchor_events = self
266            .source_shared_anchor_events
267            .saturating_add(other.source_shared_anchor_events);
268        self.source_shared_descendant_events = self
269            .source_shared_descendant_events
270            .saturating_add(other.source_shared_descendant_events);
271        self.source_unknown_events = self
272            .source_unknown_events
273            .saturating_add(other.source_unknown_events);
274        self.source_families_seen = self
275            .source_families_seen
276            .saturating_add(other.source_families_seen);
277        self.source_family_cells_seen = self
278            .source_family_cells_seen
279            .saturating_add(other.source_family_cells_seen);
280        self.source_family_shadow_eligible = self
281            .source_family_shadow_eligible
282            .saturating_add(other.source_family_shadow_eligible);
283        self.source_family_shadow_eligible_cells = self
284            .source_family_shadow_eligible_cells
285            .saturating_add(other.source_family_shadow_eligible_cells);
286        self.source_family_promoted = self
287            .source_family_promoted
288            .saturating_add(other.source_family_promoted);
289        self.source_family_promoted_cells = self
290            .source_family_promoted_cells
291            .saturating_add(other.source_family_promoted_cells);
292        self.source_family_fallback = self
293            .source_family_fallback
294            .saturating_add(other.source_family_fallback);
295        self.source_family_fallback_cells = self
296            .source_family_fallback_cells
297            .saturating_add(other.source_family_fallback_cells);
298        self.source_forward_descendants = self
299            .source_forward_descendants
300            .saturating_add(other.source_forward_descendants);
301        self.source_evidence_limit_fallbacks = self
302            .source_evidence_limit_fallbacks
303            .saturating_add(other.source_evidence_limit_fallbacks);
304        self.source_evidence_peak_bytes = self
305            .source_evidence_peak_bytes
306            .max(other.source_evidence_peak_bytes);
307        self.source_anchor_parses = self
308            .source_anchor_parses
309            .saturating_add(other.source_anchor_parses);
310        self.source_anchor_asts = self
311            .source_anchor_asts
312            .saturating_add(other.source_anchor_asts);
313        self.source_anchor_analyses = self
314            .source_anchor_analyses
315            .saturating_add(other.source_anchor_analyses);
316        self.source_descendant_strings_avoided = self
317            .source_descendant_strings_avoided
318            .saturating_add(other.source_descendant_strings_avoided);
319        self.source_descendant_events_avoided = self
320            .source_descendant_events_avoided
321            .saturating_add(other.source_descendant_events_avoided);
322        self.source_descendant_analyses_avoided = self
323            .source_descendant_analyses_avoided
324            .saturating_add(other.source_descendant_analyses_avoided);
325        self.source_compressed_families_prepared = self
326            .source_compressed_families_prepared
327            .saturating_add(other.source_compressed_families_prepared);
328        self.source_compressed_cells_prepared = self
329            .source_compressed_cells_prepared
330            .saturating_add(other.source_compressed_cells_prepared);
331        self.source_partitioned_families_seen = self
332            .source_partitioned_families_seen
333            .saturating_add(other.source_partitioned_families_seen);
334        self.source_partitioned_families_prepared = self
335            .source_partitioned_families_prepared
336            .saturating_add(other.source_partitioned_families_prepared);
337        self.source_partitioned_families_rejected = self
338            .source_partitioned_families_rejected
339            .saturating_add(other.source_partitioned_families_rejected);
340        self.source_partition_fragments_prepared = self
341            .source_partition_fragments_prepared
342            .saturating_add(other.source_partition_fragments_prepared);
343        self.source_partition_span_cells_prepared = self
344            .source_partition_span_cells_prepared
345            .saturating_add(other.source_partition_span_cells_prepared);
346        self.source_partition_fallback_cells = self
347            .source_partition_fallback_cells
348            .saturating_add(other.source_partition_fallback_cells);
349        self.source_partition_analyses_reused = self
350            .source_partition_analyses_reused
351            .saturating_add(other.source_partition_analyses_reused);
352        self.source_partition_function_semantics = self
353            .source_partition_function_semantics
354            .saturating_add(other.source_partition_function_semantics);
355        self.source_partition_holes = self
356            .source_partition_holes
357            .saturating_add(other.source_partition_holes);
358        self.source_partition_ordinary_exceptions = self
359            .source_partition_ordinary_exceptions
360            .saturating_add(other.source_partition_ordinary_exceptions);
361        self.source_partition_failures = self
362            .source_partition_failures
363            .saturating_add(other.source_partition_failures);
364        self.source_partition_surviving_cells = self
365            .source_partition_surviving_cells
366            .saturating_add(other.source_partition_surviving_cells);
367        for (reason, count) in &other.fallback_reasons {
368            let total = self.fallback_reasons.entry(reason.clone()).or_default();
369            *total = total.saturating_add(*count);
370        }
371    }
372}