Skip to content

Commit be3a699

Browse files
committed
fix: allow an explicit execution time to extend the plan end past the prod frontier
Signed-off-by: wtruongdata <quang072000@gmail.com>
1 parent b43743a commit be3a699

1 file changed

Lines changed: 29 additions & 0 deletions

File tree

sqlmesh/core/context.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1721,6 +1721,35 @@ def plan_builder(
17211721
execution_time or now(),
17221722
)
17231723

1724+
execution_time_ts = to_timestamp(execution_time) if execution_time is not None else None
1725+
if (
1726+
execution_time_ts is not None
1727+
and end is None
1728+
and default_end is not None
1729+
and execution_time_ts > default_end
1730+
):
1731+
# An explicitly provided execution time acts as the plan's effective "now", so the
1732+
# default end is allowed to extend past the recorded prod frontier instead of being
1733+
# capped by it. This mirrors how an explicit `end` causes the per-model interval end
1734+
# caps to be dropped entirely in PlanBuilder.build() (see `self.override_end`,
1735+
# sqlmesh/core/plan/builder.py line 206). Raising (rather than dropping) the caps is
1736+
# safe here because `plan --run` already runs with no caps at all.
1737+
#
1738+
# Note this raises every entry already present in max_interval_end_per_model (i.e.
1739+
# every model in this dict, which _get_max_interval_end_per_model above has already
1740+
# scoped down to backfill_models/its ancestors when a selection is in effect) - not
1741+
# just modified or explicitly selected models within that scope. That's intentional,
1742+
# not an oversight. It's what makes a plain, unscoped `sqlmesh plan --execution-time X`
1743+
# in prod report the same missing intervals as `sqlmesh plan --run --execution-time X`
1744+
# would at the same simulated time. Narrowing this further would reintroduce a `plan`
1745+
# vs `plan --run` mismatch for models within that scope.
1746+
default_end = execution_time_ts
1747+
execution_time_dt = to_datetime(execution_time_ts)
1748+
max_interval_end_per_model = {
1749+
model_fqn: max(interval_end, execution_time_dt)
1750+
for model_fqn, interval_end in max_interval_end_per_model.items()
1751+
}
1752+
17241753
# Refresh snapshot intervals to ensure that they are up to date with values reflected in the max_interval_end_per_model.
17251754
self.state_sync.refresh_snapshot_intervals(context_diff.snapshots.values())
17261755

0 commit comments

Comments
 (0)