44import typing as t
55import logging
66from dataclasses import dataclass
7+ from collections import defaultdict
78
89from rich .console import Console as RichConsole
910from rich .tree import Tree
@@ -75,8 +76,8 @@ class ExplainableRestatementStage(stages.RestatementStage):
7576 of what might happen when they ask for the plan to be explained
7677 """
7778
78- snapshot_intervals_to_clear : t .Dict [str , SnapshotIntervalClearRequest ]
79- """Which snapshots from other environments would have intervals cleared as part of restatement, keyed by name"""
79+ snapshot_intervals_to_clear : t .Dict [str , t . List [ SnapshotIntervalClearRequest ] ]
80+ """Which snapshots from other environments would have intervals cleared as part of restatement, grouped by name. """
8081
8182 @classmethod
8283 def from_restatement_stage (
@@ -92,10 +93,13 @@ def from_restatement_stage(
9293 loaded_snapshots = {s .snapshot_id : s for s in stage .all_snapshots .values ()},
9394 )
9495
96+ # Group the interval clear requests by snapshot name to make them easier to write to the console
97+ snapshot_intervals_to_clear = defaultdict (list )
98+ for clear_request in all_restatement_intervals .values ():
99+ snapshot_intervals_to_clear [clear_request .snapshot .name ].append (clear_request )
100+
95101 return cls (
96- snapshot_intervals_to_clear = {
97- s .snapshot .name : s for s in all_restatement_intervals .values ()
98- },
102+ snapshot_intervals_to_clear = snapshot_intervals_to_clear ,
99103 all_snapshots = stage .all_snapshots ,
100104 )
101105
@@ -198,15 +202,30 @@ def visit_explainable_restatement_stage(self, stage: ExplainableRestatementStage
198202 def visit_restatement_stage (
199203 self , stage : t .Union [ExplainableRestatementStage , stages .RestatementStage ]
200204 ) -> Tree :
201- tree = Tree ("[bold]Invalidate data intervals as part of restatement[/bold]" )
205+ tree = Tree (
206+ "[bold]Invalidate data intervals in state for development environments to prevent old data from being promoted[/bold]\n "
207+ "This only affects state and will not clear physical data from the tables until the next plan for each environment"
208+ )
202209
203210 if isinstance (stage , ExplainableRestatementStage ) and (
204211 snapshot_intervals := stage .snapshot_intervals_to_clear
205212 ):
206- for clear_request in snapshot_intervals .values ():
207- display_name = self ._display_name (clear_request .snapshot )
208- interval = clear_request .interval
209- tree .add (f"{ display_name } [{ to_ts (interval [0 ])} - { to_ts (interval [1 ])} ]" )
213+ for name , clear_requests in snapshot_intervals .items ():
214+ display_name = model_display_name (
215+ name , self .environment_naming_info , self .default_catalog , self .dialect
216+ )
217+ interval_start = min (cr .interval [0 ] for cr in clear_requests )
218+ interval_end = max (cr .interval [1 ] for cr in clear_requests )
219+
220+ if not interval_start or not interval_end :
221+ continue
222+
223+ node = tree .add (f"{ display_name } [{ to_ts (interval_start )} - { to_ts (interval_end )} ]" )
224+
225+ all_environment_names = sorted (
226+ set (env_name for cr in clear_requests for env_name in cr .environment_names )
227+ )
228+ node .add ("in environments: " + ", " .join (all_environment_names ))
210229
211230 return tree
212231
0 commit comments