1pub mod arrow_ingest;
6pub mod eval;
7pub mod eval_delta;
8pub mod graph;
9pub mod ingest;
10pub mod ingest_builder;
11pub mod plan;
12pub mod range_view;
13pub mod scheduler;
14pub mod spill;
15pub mod vertex;
16
17pub mod csr_edges;
19pub mod debug_views;
20pub mod delta_edges;
21pub mod interval_tree;
22pub mod named_range;
23pub mod sheet_index;
24pub mod sheet_registry;
25pub mod topo;
26pub mod vertex_store;
27
28pub mod arena;
30
31pub mod tuning;
33
34#[cfg(test)]
35mod tests;
36
37pub use eval::{Engine, EvalResult, RecalcPlan};
38pub use eval_delta::{DeltaMode, EvalDelta};
39pub use graph::snapshot::VertexSnapshot;
41pub use graph::{
42 ChangeEvent, DependencyGraph, DependencyRef, OperationSummary, StripeKey, StripeType,
43 block_index,
44};
45pub use scheduler::{Layer, Schedule, Scheduler};
46pub use vertex::{VertexId, VertexKind};
47
48pub use graph::editor::{
49 DataUpdateSummary, EditorError, MetaUpdateSummary, RangeSummary, ShiftSummary, TransactionId,
50 VertexDataPatch, VertexEditor, VertexMeta, VertexMetaPatch,
51};
52
53pub use graph::editor::change_log::{ChangeLog, ChangeLogger, NullChangeLogger};
54
55use crate::traits::EvaluationContext;
58use crate::traits::VolatileLevel;
59
60impl<R: EvaluationContext> Engine<R> {
61 pub fn begin_bulk_ingest(&mut self) -> ingest_builder::BulkIngestBuilder<'_> {
62 ingest_builder::BulkIngestBuilder::new(&mut self.graph)
63 }
64}
65
66pub trait CalcObserver: Send + Sync {
68 fn on_eval_start(&self, vertex_id: VertexId);
69 fn on_eval_complete(&self, vertex_id: VertexId, duration: std::time::Duration);
70 fn on_cycle_detected(&self, cycle: &[VertexId]);
71 fn on_dirty_propagation(&self, vertex_id: VertexId, affected_count: usize);
72}
73
74impl CalcObserver for () {
76 fn on_eval_start(&self, _vertex_id: VertexId) {}
77 fn on_eval_complete(&self, _vertex_id: VertexId, _duration: std::time::Duration) {}
78 fn on_cycle_detected(&self, _cycle: &[VertexId]) {}
79 fn on_dirty_propagation(&self, _vertex_id: VertexId, _affected_count: usize) {}
80}
81
82#[derive(Debug, Clone)]
84pub struct EvalConfig {
85 pub enable_parallel: bool,
86 pub max_threads: Option<usize>,
87 pub max_vertices: Option<usize>,
89 pub max_eval_time: Option<std::time::Duration>,
90 pub max_memory_mb: Option<usize>,
91
92 pub default_sheet_name: String,
94
95 pub workbook_seed: u64,
97
98 pub volatile_level: VolatileLevel,
100
101 pub range_expansion_limit: usize,
104
105 pub max_open_ended_rows: u32,
109
110 pub max_open_ended_cols: u32,
114
115 pub stripe_height: u32,
117 pub stripe_width: u32,
119 pub enable_block_stripes: bool,
121
122 pub spill: SpillConfig,
124
125 pub use_dynamic_topo: bool,
127 pub pk_visit_budget: usize,
129 pub pk_compaction_interval_ops: u64,
131 pub max_layer_width: Option<usize>,
133 pub pk_reject_cycle_edges: bool,
136 pub sheet_index_mode: SheetIndexMode,
138
139 pub warmup: tuning::WarmupConfig,
141
142 pub arrow_storage_enabled: bool,
144 pub delta_overlay_enabled: bool,
146
147 pub write_formula_overlay_enabled: bool,
150
151 pub date_system: DateSystem,
153
154 pub defer_graph_building: bool,
157}
158
159impl Default for EvalConfig {
160 fn default() -> Self {
161 Self {
162 enable_parallel: true,
163 max_threads: None,
164 max_vertices: None,
165 max_eval_time: None,
166 max_memory_mb: None,
167
168 default_sheet_name: format!("Sheet{}", 1),
169
170 workbook_seed: 0xF0F0_D0D0_AAAA_5555,
172
173 volatile_level: VolatileLevel::Always,
175
176 range_expansion_limit: 64,
178 max_open_ended_rows: 1_048_576,
181 max_open_ended_cols: 16_384,
182 stripe_height: 256,
183 stripe_width: 256,
184 enable_block_stripes: false,
185 spill: SpillConfig::default(),
186
187 use_dynamic_topo: false, pk_visit_budget: 50_000,
190 pk_compaction_interval_ops: 100_000,
191 max_layer_width: None,
192 pk_reject_cycle_edges: false,
193 sheet_index_mode: SheetIndexMode::Eager,
194 warmup: tuning::WarmupConfig::default(),
195 arrow_storage_enabled: true,
196 delta_overlay_enabled: true,
197 write_formula_overlay_enabled: true,
198 date_system: DateSystem::Excel1900,
199 defer_graph_building: false,
200 }
201 }
202}
203
204impl EvalConfig {
205 #[inline]
206 pub fn with_range_expansion_limit(mut self, limit: usize) -> Self {
207 self.range_expansion_limit = limit;
208 self
209 }
210
211 #[inline]
212 pub fn with_parallel(mut self, enable: bool) -> Self {
213 self.enable_parallel = enable;
214 self
215 }
216
217 #[inline]
218 pub fn with_block_stripes(mut self, enable: bool) -> Self {
219 self.enable_block_stripes = enable;
220 self
221 }
222
223 #[inline]
224 pub fn with_arrow_storage(mut self, enable: bool) -> Self {
225 self.arrow_storage_enabled = enable;
226 self
227 }
228
229 #[inline]
230 pub fn with_delta_overlay(mut self, enable: bool) -> Self {
231 self.delta_overlay_enabled = enable;
232 self
233 }
234
235 #[inline]
236 pub fn with_formula_overlay(mut self, enable: bool) -> Self {
237 self.write_formula_overlay_enabled = enable;
238 self
239 }
240
241 #[inline]
242 pub fn with_date_system(mut self, system: DateSystem) -> Self {
243 self.date_system = system;
244 self
245 }
246}
247
248#[derive(Debug, Clone, Copy, PartialEq, Eq)]
249pub enum SheetIndexMode {
250 Eager,
252 Lazy,
254 FastBatch,
256}
257
258pub use formualizer_common::DateSystem;
259
260pub fn new_engine<R>(resolver: R, config: EvalConfig) -> Engine<R>
262where
263 R: EvaluationContext + 'static,
264{
265 Engine::new(resolver, config)
266}
267
268#[derive(Debug, Clone, Copy, PartialEq, Eq)]
270pub struct SpillConfig {
271 pub conflict_policy: SpillConflictPolicy,
273 pub tiebreaker: SpillTiebreaker,
275 pub bounds_policy: SpillBoundsPolicy,
277 pub buffer_mode: SpillBufferMode,
279 pub memory_budget_bytes: Option<u64>,
281 pub cancellation: SpillCancellationPolicy,
283 pub visibility: SpillVisibility,
285}
286
287impl Default for SpillConfig {
288 fn default() -> Self {
289 Self {
290 conflict_policy: SpillConflictPolicy::Error,
291 tiebreaker: SpillTiebreaker::FirstWins,
292 bounds_policy: SpillBoundsPolicy::Strict,
293 buffer_mode: SpillBufferMode::ShadowBuffer,
294 memory_budget_bytes: None,
295 cancellation: SpillCancellationPolicy::Cooperative,
296 visibility: SpillVisibility::OnCommit,
297 }
298 }
299}
300
301#[derive(Debug, Clone, Copy, PartialEq, Eq)]
302pub enum SpillConflictPolicy {
303 Error,
304 Preempt,
305}
306
307#[derive(Debug, Clone, Copy, PartialEq, Eq)]
308pub enum SpillTiebreaker {
309 FirstWins,
310 EvaluationEpochAsc,
311 AnchorAddressAsc,
312 FunctionPriorityThenAddress,
313}
314
315#[derive(Debug, Clone, Copy, PartialEq, Eq)]
316pub enum SpillBoundsPolicy {
317 Strict,
318 Truncate,
319}
320
321#[derive(Debug, Clone, Copy, PartialEq, Eq)]
322pub enum SpillBufferMode {
323 ShadowBuffer,
324 PersistenceJournal,
325}
326
327#[derive(Debug, Clone, Copy, PartialEq, Eq)]
328pub enum SpillCancellationPolicy {
329 Cooperative,
330 Strict,
331}
332
333#[derive(Debug, Clone, Copy, PartialEq, Eq)]
334pub enum SpillVisibility {
335 OnCommit,
336 StagedLayer,
337}