Skip to content

fix(snapshot): restate exactly N monthly intervals with auto restatement - #6107

Open
breken-ai wants to merge 1 commit into
SQLMesh:mainfrom
breken-ai:fix/auto-restatement-monthly-intervals
Open

breken-ai wants to merge 1 commit into
SQLMesh:mainfrom
breken-ai:fix/auto-restatement-monthly-intervals

Conversation

@breken-ai

Copy link
Copy Markdown

Description

auto_restatement_intervals should restate the last N intervals. Snapshot.get_next_auto_restatement_interval computes the start as end - N * interval_unit.milliseconds. For a monthly model, IntervalUnit.MONTH.milliseconds is 28 days, so the start moves about 2.4 days later for every month counted back. apply_auto_restatements then floors that start to the beginning of its month.

  • Up to 12 intervals: the drift stays inside the right month, so the floor hides it.
  • 13 or more: the start falls into the next month and the oldest month is never restated.

For a monthly model with intervals through June 2024, restated on 2024-07-02:

auto_restatement_intervals restated from (main) expected
12 2023-07-01 2023-07-01
13 2023-07-01 2023-06-01
24 2022-08-01 2022-07-01

This matters when the setting is used to pick up late corrections, for example "restate the last 24 months". The oldest month is silently left out on every run and its stale data is never refreshed.

The fix steps back N intervals with the interval unit's cron, the same way expand_range and inclusive_exclusive do. For fixed-length units (day, hour, minutes) the result is the same as before, and for months and years it is calendar-exact.

Test Plan

  • Added test_apply_auto_restatements_monthly, parametrized for 1, 12, 13 and 24 intervals. It checks both the pending restatement interval and the intervals left on the snapshot. On main (263723f) the 13 and 24 cases fail (the restatement starts on 2023-07-01 and 2022-08-01) and 1 and 12 pass. All four pass with the fix.
  • The existing test_get_next_auto_restatement_interval and test_apply_auto_restatements (hourly with 24 intervals, daily with 2 and 5) still pass.
  • pytest tests/core/test_snapshot.py tests/core/test_scheduler.py: 162 passed.
  • pytest tests/core/integration -k restatement: 24 passed.
  • ruff check, ruff format --check and mypy sqlmesh/core/snapshot/definition.py are clean for the changed files.

Checklist

  • I have run make style and fixed any issues
  • I have added tests for my changes (if applicable)
  • All existing tests pass (make fast-test)
  • My commits are signed off (git commit -s) per the DCO

I ran ruff and mypy directly rather than the full pre-commit suite. I ran the snapshot, scheduler and restatement integration tests rather than the full make fast-test.

This fix was found and written with AI assistance (Claude).

`get_next_auto_restatement_interval` computed the start as
`end - N * interval_unit.milliseconds`, and a MONTH interval unit is
28 days long. For monthly models the start drifted about 2.4 days per
month, so from 13 intervals on the cron floor landed a month too late
and the oldest month was never restated (13 restated 12, 24 restated 23).

Step back N intervals with the interval unit's cron instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: breken-ai <312387581+breken-ai@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant