Skip to content

Commit bd895ba

Browse files
committed
update for more valid combos
1 parent 5898932 commit bd895ba

2 files changed

Lines changed: 16 additions & 6 deletions

File tree

docs/guides/linter.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ Here are all of SQLMesh's built-in linting rules:
7575
| `noselectstar` | Stylistic | The query's top-level selection may not be `SELECT *`, even if SQLMesh can expand the `SELECT *` into individual columns |
7676
| `nomissingaudits` | Governance | SQLMesh did not find any `audits` in the model's configuration to test data quality. |
7777
| `nomissingexternalmodels` | Governance | All external models must be registered in the external_models.yaml file |
78-
| `cronintervalalignment` | Governance | Upstream model has a cron expression with longer intervals than downstream model. Example: step_1(`@weekly`) -> step_2(`@daily`) -> step_3(`*/5 * * * *`). step_2 and step_3 are anchored to step_1's cron and will run on the same schedule as step_1. The fix is to align the schedules where a downstream model's cron is the same or has a longer cron interval than an upstream model's. |
78+
| `cronintervalalignment` | Governance | Upstream model has a cron expression with longer intervals than downstream model. Example: step_1(`@daily`) -> step_2(`@hourly`) -> step_3(`*/5 * * * *`). step_2 and step_3 will not behave as intended because their temporal grains are smaller than step_1's. step_1 will backfill all of `2020-01-01 - 2020-01-01`. step_2 will backfill every hour interval starting from `2020-01-02 00:00:00 - 2020-01-02 00:01:00`. However, it will wastefully backfill empty intervals given step_1 does not contain data for this interval. This can exacerbate scheduling inefficiencies. The fix is to align the schedules where a downstream model's cron is the same or has a longer cron interval than an upstream model's. |
7979

8080
### User-defined rules
8181

sqlmesh/core/linter/rules/builtin.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -277,11 +277,13 @@ def create_fix(self, model_name: str) -> t.Optional[Fix]:
277277
class CronIntervalAlignment(Rule):
278278
"""Upstream model has a cron expression with longer intervals than downstream model."""
279279

280-
def check_model(self, model: Model) -> t.Optional[RuleViolation]:
280+
def check_model(self, model: Model) -> t.Optional[t.List[RuleViolation]]:
281281
placeholder_start_date = "2020-01-01 10:00:00"
282282

283283
this_model_cron_next = model.cron_next(placeholder_start_date)
284284

285+
violations = []
286+
has_valid_upstream = False
285287
for upstream_model_name in model.depends_on:
286288
upstream_model = self.context.get_model(upstream_model_name)
287289

@@ -297,11 +299,19 @@ def check_model(self, model: Model) -> t.Optional[RuleViolation]:
297299
upstream_model_cron_next = upstream_model.cron_next(placeholder_start_date)
298300

299301
if upstream_model_cron_next > this_model_cron_next:
300-
return self.violation(
301-
f"Upstream model {upstream_model_name} has longer cron interval ({upstream_model.cron}) "
302-
f"than this model ({model.cron})"
302+
violations.append(
303+
RuleViolation(
304+
rule=self,
305+
violation_msg=f"Upstream model {upstream_model_name} has longer cron interval ({upstream_model.cron}) "
306+
f"than this model ({model.cron})",
307+
)
303308
)
304-
return None
309+
elif upstream_model_cron_next <= this_model_cron_next:
310+
has_valid_upstream = True
311+
break
312+
if has_valid_upstream:
313+
return None
314+
return violations
305315

306316

307317
BUILTIN_RULES = RuleSet(subclasses(__name__, Rule, (Rule,)))

0 commit comments

Comments
 (0)