codeant-ai-for-open-source[bot] commented on code in PR #42481:
URL: https://github.com/apache/superset/pull/42481#discussion_r3681727810


##########
superset/commands/report/execute.py:
##########
@@ -1195,10 +1377,26 @@ class ReportNotTriggeredErrorState(BaseReportState):
     - Error
     """
 
-    current_states = [ReportState.NOOP, ReportState.ERROR]
+    current_states = [ReportState.NOOP, ReportState.ERROR, 
ReportState.RETRYING]
     initial = True
 
     def next(self) -> None:  # noqa: C901
+        # If retries from a previous crontab window are still in-flight and
+        # this is a new crontab trigger, skip — let the active retry chain
+        # finish.  The stale-window check uses normalized (naive) datetimes
+        # so tz-aware vs naive mismatches don't cause false positives.
+        if (
+            self._report_schedule.last_state == ReportState.RETRYING
+            and self._is_retry_window_stale()
+        ):
+            logger.info(
+                "Skipping crontab execution for report %s — retries from a "
+                "previous window are still in-flight (execution %s)",
+                self._report_schedule.id,
+                self._execution_id,
+            )
+            return

Review Comment:
   **Suggestion:** This branch permanently drops a newly scheduled crontab 
window when an older retry chain is active. It returns without advancing 
`last_eval_dttm`, recording an execution, or enqueuing the new window; because 
the scheduler continues to produce future windows, this particular window is 
never retried after the old chain finishes. The new-window execution must be 
deferred and re-enqueued, or otherwise recorded so it is not lost. [incomplete 
implementation]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Scheduled report windows can be silently skipped.
   - ❌ Alert evaluations may miss their next scheduled check.
   - ⚠️ Users receive no execution log for skipped windows.
   ```
   </details>
   
   [![Fix in 
Cursor](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-cursor-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=3c23da30c81b4a988efc3c60da4db602&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
 [![Fix in VSCode 
Claude](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-vscode-claude-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=3c23da30c81b4a988efc3c60da4db602&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
   
   *(Use Cmd/Ctrl + Click for best experience)*
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset/commands/report/execute.py
   **Line:** 1388:1398
   **Comment:**
        *Incomplete Implementation: This branch permanently drops a newly 
scheduled crontab window when an older retry chain is active. It returns 
without advancing `last_eval_dttm`, recording an execution, or enqueuing the 
new window; because the scheduler continues to produce future windows, this 
particular window is never retried after the old chain finishes. The new-window 
execution must be deferred and re-enqueued, or otherwise recorded so it is not 
lost.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   Once fix is implemented, also check other comments on the same PR, and ask 
user if the user wants to fix the rest of the comments as well. if said yes, 
then fetch all the comments validate the correctness and implement a minimal fix
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F42481&comment_hash=cde04d64be83a84e557f972e8984cfe1bce39e9821623579bc4afb08861f78ea&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F42481&comment_hash=cde04d64be83a84e557f972e8984cfe1bce39e9821623579bc4afb08861f78ea&reaction=dislike'>👎</a>



##########
superset/commands/report/execute.py:
##########
@@ -1165,6 +1165,188 @@ def is_in_error_grace_period(self) -> bool:
             < last_success.end_dttm
         )
 
+    def _get_retry_delay(self, attempt: int) -> int:
+        """Exponential backoff: base * 2^attempt, capped at a configurable 
max."""
+        base: int = app.config.get("ALERT_REPORTS_RETRY_BASE_DELAY_SECONDS", 
60)
+        cap: int = app.config.get("ALERT_REPORTS_RETRY_MAX_DELAY_SECONDS", 
3600)
+        return min(base * (2**attempt), cap)
+
+    @staticmethod
+    def _normalize_dttm(dt: Optional[datetime]) -> Optional[datetime]:
+        """Strip timezone info so naive/aware datetimes can be compared."""
+        if dt is not None and dt.tzinfo is not None:
+            return dt.replace(tzinfo=None)
+        return dt
+
+    def _is_retry_window_stale(self) -> bool:
+        """
+        Return True if a new crontab window fired while the previous one was
+        still retrying.  When stale the retry counter must be reset so the new
+        window gets a fresh retry budget.
+
+        Both sides are normalized to naive datetimes because
+        retry_scheduled_dttm is a plain DateTime column (no timezone), while
+        _scheduled_dttm may be tz-aware depending on the Celery broker.
+        """
+        anchor = 
self._normalize_dttm(self._report_schedule.retry_scheduled_dttm)
+        current = self._normalize_dttm(self._scheduled_dttm)
+        return anchor is not None and anchor != current
+
+    def _increment_retry(self) -> int:
+        """Increment retry_attempt, set the window anchor, and return the new 
count."""
+        self._report_schedule.retry_attempt += 1
+        # Store as naive — the column is a plain DateTime.
+        self._report_schedule.retry_scheduled_dttm = self._normalize_dttm(
+            self._scheduled_dttm
+        )
+        return self._report_schedule.retry_attempt

Review Comment:
   **Suggestion:** The retry counter is modified on the ORM object and then 
persisted without acquiring a row lock or performing an atomic 
compare-and-update. Two duplicate Celery executions can both observe the same 
`retry_attempt`, each enqueue another retry, and overwrite the retry anchor, 
causing duplicate report deliveries and exceeding the configured retry budget. 
[race condition]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Duplicate retry tasks can deliver duplicate reports.
   - ❌ Retry budgets can be exceeded under overlapping execution.
   - ⚠️ Retry state anchors can be overwritten by stale workers.
   ```
   </details>
   
   [![Fix in 
Cursor](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-cursor-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=2f290fca1ee046e38014a75a53fc6b56&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
 [![Fix in VSCode 
Claude](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-vscode-claude-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=2f290fca1ee046e38014a75a53fc6b56&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
   
   *(Use Cmd/Ctrl + Click for best experience)*
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset/commands/report/execute.py
   **Line:** 1195:1202
   **Comment:**
        *Race Condition: The retry counter is modified on the ORM object and 
then persisted without acquiring a row lock or performing an atomic 
compare-and-update. Two duplicate Celery executions can both observe the same 
`retry_attempt`, each enqueue another retry, and overwrite the retry anchor, 
causing duplicate report deliveries and exceeding the configured retry budget.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   Once fix is implemented, also check other comments on the same PR, and ask 
user if the user wants to fix the rest of the comments as well. if said yes, 
then fetch all the comments validate the correctness and implement a minimal fix
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F42481&comment_hash=39935f9cf1ca1e9625a44e6ba099e43e07d3e9c99427e1d2e37a88cab420d732&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F42481&comment_hash=39935f9cf1ca1e9625a44e6ba099e43e07d3e9c99427e1d2e37a88cab420d732&reaction=dislike'>👎</a>



##########
superset/migrations/versions/2026-07-28_00-00_f3a8c1d2e9b7_add_report_retry_state_columns.py:
##########
@@ -0,0 +1,84 @@
+# 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_report_retry_columns
+
+Revision ID: f3a8c1d2e9b7
+Revises: d3b9a1f6c204
+Create Date: 2026-07-28 00:00:00.000000
+
+"""
+
+import logging
+
+import sqlalchemy as sa
+from alembic import op
+
+from superset.migrations.shared.utils import get_table_column
+
+logger = logging.getLogger("alembic.env")
+
+# revision identifiers, used by Alembic.
+revision = "f3a8c1d2e9b7"
+down_revision = "d3b9a1f6c204"
+
+# Configuration columns (user-configurable)
+_CONFIG_COLUMNS = [
+    ("retry_on_failure", sa.Boolean(), False, "0"),
+    ("retry_max_attempts", sa.Integer(), False, "3"),
+    ("send_failed_reports", sa.Boolean(), False, "0"),
+    ("retry_notify_owners", sa.Boolean(), False, "1"),
+    ("retry_notify_recipients", sa.Boolean(), False, "0"),
+]
+
+# State columns (written by the execution engine)
+_STATE_COLUMNS = [
+    ("retry_attempt", sa.Integer(), False, "0"),
+    ("retry_scheduled_dttm", sa.DateTime(), True, None),
+]
+
+
+def upgrade() -> None:
+    """Add retry config and state columns to report_schedule."""
+    if get_table_column("report_schedule", "retry_attempt") is not None:
+        logger.info(
+            "Column report_schedule.retry_attempt already exists. Skipping 
migration."
+        )
+        return

Review Comment:
   **Suggestion:** Using only `retry_attempt` as the migration-completion 
marker makes the migration non-recoverable after a partial DDL application. If 
that column was created but any later retry column was not, a rerun returns 
early and leaves the model querying nonexistent columns. Check that every 
expected column exists, or add missing columns individually. [possible bug]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Failed upgrades can leave report execution unusable.
   - ❌ Retry configuration fields may be missing after migration reruns.
   - ⚠️ Operators must manually repair partially applied schemas.
   ```
   </details>
   
   [![Fix in 
Cursor](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-cursor-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=07d912c711ab476fab8c68c980cce43d&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
 [![Fix in VSCode 
Claude](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-vscode-claude-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=07d912c711ab476fab8c68c980cce43d&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
   
   *(Use Cmd/Ctrl + Click for best experience)*
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset/migrations/versions/2026-07-28_00-00_f3a8c1d2e9b7_add_report_retry_state_columns.py
   **Line:** 56:60
   **Comment:**
        *Possible Bug: Using only `retry_attempt` as the migration-completion 
marker makes the migration non-recoverable after a partial DDL application. If 
that column was created but any later retry column was not, a rerun returns 
early and leaves the model querying nonexistent columns. Check that every 
expected column exists, or add missing columns individually.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   Once fix is implemented, also check other comments on the same PR, and ask 
user if the user wants to fix the rest of the comments as well. if said yes, 
then fetch all the comments validate the correctness and implement a minimal fix
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F42481&comment_hash=6b266d770ed29f8db49be66f8401afb93024c4a0b006f21f0889edf4f2dadfb2&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F42481&comment_hash=6b266d770ed29f8db49be66f8401afb93024c4a0b006f21f0889edf4f2dadfb2&reaction=dislike'>👎</a>



##########
superset/commands/report/execute.py:
##########
@@ -1403,10 +1606,15 @@ def next(self) -> None:
             warning_message = (
                 ";".join(self._filter_warnings) if self._filter_warnings else 
None
             )
+            # Clear any retry state from previous failed attempts in this 
window.
+            self._reset_retry_counter()
             self.update_report_schedule_and_log(
                 ReportState.SUCCESS, error_message=warning_message
             )
         except Exception as ex:  # pylint: disable=broad-except
+            if self._handle_retry_or_error(str(ex), ex):
+                return  # retry scheduled — exit cleanly

Review Comment:
   **Suggestion:** The retry handler is invoked only from the report send 
failure path shown here. For alerts that are already in `SUCCESS` or `GRACE`, 
failures from the preceding `AlertCommand.run()` are handled by the separate 
alert exception branch and bypass `_handle_retry_or_error`, so configured 
retries do not apply to those alert evaluations. Route that alert failure path 
through the same retry logic. [incomplete implementation]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Configured retries do not cover alert evaluation failures.
   - ❌ Transient alert query failures immediately enter ERROR.
   - ⚠️ Alert owners receive failure notifications without retry attempts.
   ```
   </details>
   
   [![Fix in 
Cursor](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-cursor-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=f8578cbf23c44d808b2c78f00985a8ae&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
 [![Fix in VSCode 
Claude](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-vscode-claude-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=f8578cbf23c44d808b2c78f00985a8ae&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
   
   *(Use Cmd/Ctrl + Click for best experience)*
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset/commands/report/execute.py
   **Line:** 1615:1616
   **Comment:**
        *Incomplete Implementation: The retry handler is invoked only from the 
report send failure path shown here. For alerts that are already in `SUCCESS` 
or `GRACE`, failures from the preceding `AlertCommand.run()` are handled by the 
separate alert exception branch and bypass `_handle_retry_or_error`, so 
configured retries do not apply to those alert evaluations. Route that alert 
failure path through the same retry logic.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   Once fix is implemented, also check other comments on the same PR, and ask 
user if the user wants to fix the rest of the comments as well. if said yes, 
then fetch all the comments validate the correctness and implement a minimal fix
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F42481&comment_hash=25c14c84d44c460dd8687439f95a53807289d0ee0c4d98f6aa7b985de84d6d58&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F42481&comment_hash=25c14c84d44c460dd8687439f95a53807289d0ee0c4d98f6aa7b985de84d6d58&reaction=dislike'>👎</a>



##########
superset/reports/api.py:
##########
@@ -147,6 +147,11 @@ def ensure_alert_reports_enabled(self) -> 
Optional[Response]:
         "validator_type",
         "working_timeout",
         "email_subject",
+        "retry_on_failure",
+        "retry_max_attempts",
+        "send_failed_reports",
+        "retry_notify_owners",
+        "retry_notify_recipients",

Review Comment:
   **Suggestion:** The retry fields are exposed in `show_columns`, but they are 
absent from `add_columns` and `edit_columns`, so FAB filters them out of create 
and update requests before persistence. The UI can submit these settings 
successfully while the database retains the defaults. Add all retry fields to 
the writable column configuration as well. [api mismatch]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ UI retry settings cannot be persisted.
   - ❌ Reports continue using default retry behavior.
   - ⚠️ GET responses falsely suggest settings were accepted.
   ```
   </details>
   
   [![Fix in 
Cursor](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-cursor-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=6429313e4c884b3c8f650cbd48934969&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
 [![Fix in VSCode 
Claude](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-vscode-claude-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=6429313e4c884b3c8f650cbd48934969&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
   
   *(Use Cmd/Ctrl + Click for best experience)*
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset/reports/api.py
   **Line:** 150:154
   **Comment:**
        *Api Mismatch: The retry fields are exposed in `show_columns`, but they 
are absent from `add_columns` and `edit_columns`, so FAB filters them out of 
create and update requests before persistence. The UI can submit these settings 
successfully while the database retains the defaults. Add all retry fields to 
the writable column configuration as well.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   Once fix is implemented, also check other comments on the same PR, and ask 
user if the user wants to fix the rest of the comments as well. if said yes, 
then fetch all the comments validate the correctness and implement a minimal fix
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F42481&comment_hash=47b6693402f2d33275f986798ec481a50127747cccfbc2f7121f047e7be8450c&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F42481&comment_hash=47b6693402f2d33275f986798ec481a50127747cccfbc2f7121f047e7be8450c&reaction=dislike'>👎</a>



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


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to