@@ -50,7 +50,7 @@ use std::rc::Rc;
5050
5151use asap_types:: post_asap:: {
5252 GroupingStrategy , HydraParams , SketchAlgorithm , SketchParams , SketchQuery , SummaryExpr ,
53- SummaryFamilyType , SummaryNode ,
53+ SummaryFamilyType , SummaryMaintenanceLifecycleGuarantee , SummaryNode ,
5454} ;
5555use asap_types:: pre_asap:: agg_intent:: AggIntent ;
5656use asap_types:: pre_asap:: expr_ir:: ColumnRef ;
@@ -99,6 +99,15 @@ pub struct CseCandidate<'a> {
9999#[ derive( Debug , Clone , Copy , PartialEq , PartialOrd ) ]
100100pub struct Cost ( pub f64 ) ;
101101
102+ /// One physical summary state and the lifecycle selected for that exact DAG
103+ /// node. Node identity is preserved so whole-DAG models can bind per-state
104+ /// evidence without relying on traversal order.
105+ pub struct CostedSummaryDeployment < ' a > {
106+ pub summary : & ' a SummaryNode ,
107+ pub guarantee : & ' a SummaryMaintenanceLifecycleGuarantee ,
108+ pub selected_cost : Cost ,
109+ }
110+
102111impl Cost {
103112 /// The cost of an operation that costs nothing at all.
104113 pub const ZERO : Cost = Cost ( 0.0 ) ;
@@ -543,6 +552,17 @@ pub trait CostModel {
543552 SummaryMaintenanceLifecycleCostInputs :: default ( )
544553 }
545554
555+ /// Horizon-aware form used by lifecycle planning. Models whose retention
556+ /// objective is capacity rather than byte-seconds can normalize their
557+ /// rate so the horizon integral equals one peak-capacity charge.
558+ fn summary_maintenance_lifecycle_cost_inputs_for_horizon (
559+ & self ,
560+ summary : & SummaryNode ,
561+ _horizon : Option < Horizon > ,
562+ ) -> SummaryMaintenanceLifecycleCostInputs {
563+ self . summary_maintenance_lifecycle_cost_inputs ( summary)
564+ }
565+
546566 /// Physical update/merge/delete support for one concrete summary. The
547567 /// conservative default advertises no long-lived maintenance capability.
548568 fn summary_maintenance_capabilities (
@@ -552,12 +572,44 @@ pub trait CostModel {
552572 SummaryMaintenanceCapabilities :: default ( )
553573 }
554574
575+ /// Replace the sum of selected per-state lifecycle costs with a complete
576+ /// root-DAG cost. The default preserves legacy models. Evidence-strict
577+ /// models return `None` when any root operation is unavailable; callers
578+ /// must not then reuse the partial per-state sum.
579+ fn complete_summary_candidate_cost (
580+ & self ,
581+ _root : & SummaryNode ,
582+ _target : Option < & QueryExpr > ,
583+ deployments : & [ CostedSummaryDeployment < ' _ > ] ,
584+ _horizon : Option < Horizon > ,
585+ _expected_reads : Option < f64 > ,
586+ ) -> Option < Cost > {
587+ Some ( Cost (
588+ deployments
589+ . iter ( )
590+ . map ( |deployment| deployment. selected_cost . 0 )
591+ . sum ( ) ,
592+ ) )
593+ }
594+
555595 /// Cost of evaluating `target` directly from its logical/raw inputs once.
556596 /// When known, lifecycle-aware materialization compares this fallback with
557597 /// the aggregate cost of the selected summary deployments.
558598 fn raw_query_recompute_cost ( & self , _target : & QueryExpr ) -> Option < Cost > {
559599 None
560600 }
601+
602+ /// Complete raw cost over the comparison context. The default preserves
603+ /// per-read models; context-aware models override this when raw input
604+ /// cardinality changes between evaluations.
605+ fn raw_query_recompute_total_cost (
606+ & self ,
607+ target : & QueryExpr ,
608+ expected_reads : f64 ,
609+ ) -> Option < Cost > {
610+ self . raw_query_recompute_cost ( target)
611+ . map ( |per_read| Cost ( per_read. 0 * expected_reads) )
612+ }
561613}
562614
563615fn sketch_state (
0 commit comments