29
29
from sqlmesh .core .snapshot .definition import check_ready_intervals
30
30
from sqlmesh .core .snapshot .definition import (
31
31
Interval ,
32
+ SnapshotEvaluationTriggers ,
32
33
expand_range ,
33
34
parent_snapshots_by_name ,
34
35
)
@@ -223,6 +224,7 @@ def run(
223
224
ignore_cron : bool = False ,
224
225
end_bounded : bool = False ,
225
226
selected_snapshots : t .Optional [t .Set [str ]] = None ,
227
+ selected_snapshots_auto_upstream : t .Optional [t .Set [str ]] = None ,
226
228
circuit_breaker : t .Optional [t .Callable [[], bool ]] = None ,
227
229
deployability_index : t .Optional [DeployabilityIndex ] = None ,
228
230
auto_restatement_enabled : bool = False ,
@@ -239,6 +241,7 @@ def run(
239
241
ignore_cron = ignore_cron ,
240
242
end_bounded = end_bounded ,
241
243
selected_snapshots = selected_snapshots ,
244
+ selected_snapshots_auto_upstream = selected_snapshots_auto_upstream ,
242
245
circuit_breaker = circuit_breaker ,
243
246
deployability_index = deployability_index ,
244
247
auto_restatement_enabled = auto_restatement_enabled ,
@@ -374,7 +377,7 @@ def run_merged_intervals(
374
377
run_environment_statements : bool = False ,
375
378
audit_only : bool = False ,
376
379
restatements : t .Optional [t .Dict [SnapshotId , Interval ]] = None ,
377
- auto_restatement_triggers : t .Dict [SnapshotId , t . List [ SnapshotId ] ] = {},
380
+ snapshot_evaluation_triggers : t .Dict [SnapshotId , SnapshotEvaluationTriggers ] = {},
378
381
) -> t .Tuple [t .List [NodeExecutionFailedError [SchedulingUnit ]], t .List [SchedulingUnit ]]:
379
382
"""Runs precomputed batches of missing intervals.
380
383
@@ -477,7 +480,9 @@ def evaluate_node(node: SchedulingUnit) -> None:
477
480
evaluation_duration_ms ,
478
481
num_audits - num_audits_failed ,
479
482
num_audits_failed ,
480
- auto_restatement_triggers = auto_restatement_triggers .get (snapshot .snapshot_id ),
483
+ snapshot_evaluation_triggers = snapshot_evaluation_triggers .get (
484
+ snapshot .snapshot_id
485
+ ),
481
486
)
482
487
483
488
try :
@@ -588,6 +593,7 @@ def _run_or_audit(
588
593
ignore_cron : bool = False ,
589
594
end_bounded : bool = False ,
590
595
selected_snapshots : t .Optional [t .Set [str ]] = None ,
596
+ selected_snapshots_auto_upstream : t .Optional [t .Set [str ]] = None ,
591
597
circuit_breaker : t .Optional [t .Callable [[], bool ]] = None ,
592
598
deployability_index : t .Optional [DeployabilityIndex ] = None ,
593
599
auto_restatement_enabled : bool = False ,
@@ -611,6 +617,7 @@ def _run_or_audit(
611
617
end_bounded: If set to true, the evaluated intervals will be bounded by the target end date, disregarding lookback,
612
618
allow_partials, and other attributes that could cause the intervals to exceed the target end date.
613
619
selected_snapshots: A set of snapshot names to run. If not provided, all snapshots will be run.
620
+ selected_snapshots_auto_upstream: The set of selected_snapshots that were automatically added because they're upstream of a selected snapshot.
614
621
circuit_breaker: An optional handler which checks if the run should be aborted.
615
622
deployability_index: Determines snapshots that are deployable in the context of this render.
616
623
auto_restatement_enabled: Whether to enable auto restatements.
@@ -666,6 +673,42 @@ def _run_or_audit(
666
673
if not merged_intervals :
667
674
return CompletionStatus .NOTHING_TO_DO
668
675
676
+ merged_intervals_snapshots = {
677
+ snapshot .snapshot_id : snapshot for snapshot in merged_intervals .keys ()
678
+ }
679
+ select_snapshot_triggers : t .Dict [SnapshotId , t .List [SnapshotId ]] = {}
680
+ if selected_snapshots and selected_snapshots_auto_upstream :
681
+ # actually selected snapshots are their own triggers
682
+ selected_snapshots_no_auto_upstream = (
683
+ selected_snapshots - selected_snapshots_auto_upstream
684
+ )
685
+ select_snapshot_triggers = {
686
+ s_id : [s_id ]
687
+ for s_id in [
688
+ snapshot_id
689
+ for snapshot_id in merged_intervals_snapshots
690
+ if snapshot_id .name in selected_snapshots_no_auto_upstream
691
+ ]
692
+ }
693
+
694
+ # trace upstream by reversing dag of all snapshots to evaluate
695
+ reversed_intervals_dag = snapshots_to_dag (merged_intervals_snapshots .values ()).reversed
696
+ for s_id in reversed_intervals_dag :
697
+ if s_id not in select_snapshot_triggers :
698
+ triggers = []
699
+ for parent_s_id in merged_intervals_snapshots [s_id ].parents :
700
+ triggers .extend (select_snapshot_triggers [parent_s_id ])
701
+ select_snapshot_triggers [s_id ] = list (dict .fromkeys (triggers ))
702
+
703
+ all_snapshot_triggers : t .Dict [SnapshotId , SnapshotEvaluationTriggers ] = {
704
+ s_id : SnapshotEvaluationTriggers (
705
+ ignore_cron = ignore_cron ,
706
+ auto_restatement_triggers = auto_restatement_triggers .get (s_id , []),
707
+ select_snapshot_triggers = select_snapshot_triggers .get (s_id , []),
708
+ )
709
+ for s_id in merged_intervals_snapshots
710
+ if ignore_cron or s_id in auto_restatement_triggers or s_id in select_snapshot_triggers
711
+ }
669
712
errors , _ = self .run_merged_intervals (
670
713
merged_intervals = merged_intervals ,
671
714
deployability_index = deployability_index ,
@@ -677,7 +720,7 @@ def _run_or_audit(
677
720
run_environment_statements = run_environment_statements ,
678
721
audit_only = audit_only ,
679
722
restatements = remove_intervals ,
680
- auto_restatement_triggers = auto_restatement_triggers ,
723
+ snapshot_evaluation_triggers = all_snapshot_triggers ,
681
724
)
682
725
683
726
return CompletionStatus .FAILURE if errors else CompletionStatus .SUCCESS
0 commit comments