harjothkhara opened a new pull request, #70089:
URL: https://github.com/apache/airflow/pull/70089

   ## Why
   
   `CronMixin._get_prev` can return a tick that is not strictly earlier than 
the time it is asked about, so a manually triggered run gets a bad data 
interval on the two days a year the clocks change.
   
   With `CronDataIntervalTimetable("0 2 * * *", timezone="America/New_York")`, 
a manual run at `2024-03-10 07:30Z`:
   
   ```
   data interval: 2024-03-10 07:00Z -> 2024-03-10 07:00Z   (zero length)
   ```
   
   The scheduled path returns the correct `2024-03-09 07:00Z -> 2024-03-10 
07:00Z` for the same period, so the two paths disagree about the same run.
   
   croniter steps back on naive wall-clock time, but `make_aware` maps a tick 
that falls in a spring-forward gap onto the next real instant. When the 
previous tick is in the gap it lands on `current`, and `_get_prev` returns 
`current` itself.
   
   The same remapping overshoots on the fall-back side. With `0 1 * * *` in 
`America/New_York` at `2024-11-03 05:30Z`, `_get_prev` returns `06:00Z` — half 
an hour in the future — and the inferred interval ends after `run_after`. 
`CronTriggerTimetable` with `run_immediately=True` picks that future tick as 
the run to fire now.
   
   The zero-length interval has a second effect. `next_dagrun_info` treats a 
zero-length previous interval as a point-in-time run and advances one period 
(#66132, which is correct for the `CronTriggerTimetable` case it was written 
for). Fed this interval it skips a whole day:
   
   ```
   after the buggy interval : 2024-03-11 06:00Z -> 2024-03-12 06:00Z
   if the interval is right : 2024-03-10 07:00Z -> 2024-03-11 06:00Z
   ```
   
   Also reproduces with `Europe/Zurich` `0 2 * * *` at 2023-03-26, and in 
`Australia/Sydney` and `Australia/Lord_Howe`.
   
   ## What
   
   - `_get_prev` keeps stepping `cron.get_prev` until the converted result is 
strictly earlier than `current`. `get_prev` is strictly decreasing on naive 
time, so it terminates.
   - The `_covers_every_hour` branch is left alone. It computes a wall-clock 
delta rather than going through `make_aware`, and the delta is strictly 
positive, so it cannot produce this.
   - Docstring now states the strictly-earlier guarantee that callers already 
assume.
   
   Over 23,040 sampled (cron, timezone, instant) combinations across eight 
timezones, 31 results change: 17 in `_get_prev`, 12 in `_align_to_prev`, 2 in 
`_align_to_next`. In every one the old value was already wrong — at or after 
the instant asked about, or a period skipped. Nothing outside a DST transition 
window changes.
   
   I also checked `_get_next` for the mirror problem and did not find one — it 
never returned a value at or before its input across 7,680 sampled instants 
around transitions. It does skip the second occurrence of an ambiguous hour, 
but that is the existing `fold=1` policy in `make_aware` and is what 
`test_fold_scheduling` expects, so I left it out.
   
   ## Testing
   
   Three regression tests, all failing before the change and passing after:
   
   - `test_cron_infer_manual_data_interval_dst` — gap and fold for 
`America/New_York`, `Europe/Zurich` and `Australia/Lord_Howe` (a 30-minute 
offset). Asserts the interval is non-empty and does not end after `run_after`.
   - `test_cron_next_dagrun_info_after_dst_manual_run` — the skipped period.
   - `test_cron_trigger_run_immediately_does_not_pick_future_run` — 
`CronTriggerTimetable`, which shares the mixin.
   
   `airflow-core/tests/unit/timetables/` is 246 passed.
   
   ---
   
   ##### Was generative AI tooling used to co-author this PR?
   
   - [X] Yes (please specify the tool below)
   
   Generated-by: Claude Opus 4.8 following [the 
guidelines](https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to