Lee-W commented on code in PR #68778:
URL: https://github.com/apache/airflow/pull/68778#discussion_r3491065376


##########
airflow-core/src/airflow/partition_mappers/rerun_policy.py:
##########
@@ -0,0 +1,55 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from enum import Enum
+
+
+class RerunPolicy(str, Enum):
+    """
+    Core-side mirror of the SDK :class:`airflow.sdk.RerunPolicy`.
+
+    Decides what the scheduler does when an upstream partition is cleared and
+    re-run after a rollup's downstream window has already fired. See the SDK
+    class for the authoring-facing documentation; the two are serialized by
+    string value so they round-trip across the Dag-parse / scheduler boundary.
+
+    ``HOLD`` (default): queue a provisional run that waits for the entire 
window
+    to re-materialize before firing again. This is the historical behavior, so 
it
+    is the default to keep existing Dags unchanged.
+
+    ``REFRESH``: re-fire the downstream Dag run immediately so it reprocesses 
with
+    the corrected upstream data.
+
+    ``IGNORE``: drop the late upstream event; do not re-fire.
+
+    ``NONE``: rerun handling does not apply — reported by non-rollup mappers 
and
+    stamped on a window's first materialization (which is not a rerun).
+    """
+
+    REFRESH = "refresh"
+    HOLD = "hold"
+    IGNORE = "ignore"
+    NONE = "none"
+
+    def fires_immediately(self) -> bool:

Review Comment:
   looks like property to me
   
   ```suggestion
       @property
       def fires_immediately(self) -> bool:
   ```



##########
airflow-core/docs/migrations-ref.rst:
##########
@@ -39,7 +39,9 @@ Here's the list of all the Database Migrations that are 
executed via when you ru
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
 | Revision ID             | Revises ID       | Airflow Version   | Description 
                                                 |
 
+=========================+==================+===================+==============================================================+
-| ``d2f4e1b3c5a7`` (head) | ``9ff64e1c35d3`` | ``3.3.0``         | Add 
partition_date to asset_partition_dag_run.               |
+| ``623bce373cdf`` (head) | ``d2f4e1b3c5a7`` | ``3.3.0``         | Add 
rerun_policy to AssetPartitionDagRun.                    |

Review Comment:
   I don' think we'll make it in 3.3.0. so that's make it 3.4.0



##########
task-sdk/src/airflow/sdk/definitions/partition_mappers/rerun_policy.py:
##########
@@ -0,0 +1,63 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from enum import Enum
+
+
+class RerunPolicy(str, Enum):
+    """
+    How a rollup reacts when an upstream partition is re-emitted after its 
downstream window already fired.
+
+    A rollup fires its downstream Dag run once the window is satisfied (e.g. a
+    monthly rollup fires once all of March's daily partitions arrive). If an
+    upstream partition that the fired window already consumed is later cleared
+    and re-run, a fresh asset event arrives for an already-materialized window.
+    This policy decides what the scheduler does with it.
+
+    ``HOLD`` (default): queue a provisional run that waits for the *entire*
+    window to re-materialize before firing again. A single re-run does not
+    re-fire; only a full recompute of the window does. This is the historical
+    behavior of a rollup before this policy existed, so it is the default to 
keep
+    existing Dags unchanged.
+
+    ``REFRESH``: re-fire the downstream Dag run so it reprocesses with the
+    corrected upstream data. The rest of the window is still materialized, so 
the
+    refresh run fires immediately rather than waiting for the whole window to
+    re-arrive. This mirrors how a non-partitioned asset-triggered Dag re-runs 
on
+    every new asset event.
+
+    ``IGNORE``: drop the late upstream event. The downstream Dag run is not
+    re-fired and no provisional run is queued.
+
+    ``NONE``: rerun handling does not apply. This is the value reported by
+    non-rollup mappers and stamped on a window's first materialization (which 
is
+    not a rerun); it is not a meaningful choice for a rollup.
+    """
+
+    REFRESH = "refresh"
+    HOLD = "hold"
+    IGNORE = "ignore"
+    NONE = "none"
+
+    def fires_immediately(self) -> bool:

Review Comment:
   same. a good idea to make them properties



##########
task-sdk/tests/task_sdk/definitions/test_partition_mappers.py:
##########
@@ -67,6 +68,77 @@ class _AlphaWindow(Window):
         RollupMapper(upstream_mapper=_StringOnlyMapper(), 
window=_AlphaWindow())
 
 
+class TestSdkRollupMapperRerunPolicy:
+    """``rerun_policy`` defaults to HOLD, coerces strings, and rejects junk."""
+
+    def _mapper(self, **kwargs):

Review Comment:
   ```suggestion
       def _make_mapper(self, **kwargs):
   ```



##########
airflow-core/src/airflow/migrations/versions/0124_3_3_0_add_rerun_policy_to_apdr.py:
##########
@@ -0,0 +1,60 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""
+Add rerun_policy to AssetPartitionDagRun.
+
+The ``rerun_policy`` column stores the RerunPolicy (as its string value) that
+governs how the scheduler fires this provisional partition Dag run. A run 
stamped
+``"refresh"`` fires immediately after an upstream partition was cleared and
+re-run; everything else is stamped ``"none"`` and goes through normal 
evaluation.
+
+Revision ID: 623bce373cdf
+Revises: d2f4e1b3c5a7
+Create Date: 2026-06-17 00:00:00.000000
+
+"""
+
+from __future__ import annotations
+
+import sqlalchemy as sa
+from alembic import op
+
+from airflow.migrations.utils import disable_sqlite_fkeys
+
+revision = "623bce373cdf"
+down_revision = "d2f4e1b3c5a7"
+branch_labels = None
+depends_on = None
+airflow_version = "3.3.0"

Review Comment:
   ```suggestion
   airflow_version = "3.4.0"
   ```



##########
airflow-core/tests/unit/timetables/test_base_timetable.py:
##########
@@ -114,6 +114,58 @@ def 
test_compute_rollup_fingerprint_window_change_produces_different_fingerprint
     assert fp_hour != fp_day
 
 
+def test_compute_rollup_fingerprint_excludes_rerun_policy():
+    """
+    Changing only ``rerun_policy`` must NOT change the fingerprint.
+
+    ``rerun_policy`` governs post-fire behavior, not which upstream keys a 
window
+    requires. If it fed the fingerprint, a policy-only edit would discard 
in-flight
+    APDRs, and upgrading from a version that pre-dates the key would invalidate
+    every pending partition run (stored fingerprints lack the key).
+    """
+    from airflow.sdk import Asset, HourWindow, RerunPolicy, RollupMapper, 
StartOfHourMapper

Review Comment:
   I think we can move most of these inline imports to the top. (just tested it 
locally)



-- 
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