You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by el...@apache.org on 2026/06/16 00:15:46 UTC

(superset) branch fix/report-tab-permalink-pre-commit created (now 59f36997cfc)

This is an automated email from the ASF dual-hosted git repository.

eschutho pushed a change to branch fix/report-tab-permalink-pre-commit
in repository https://gitbox.apache.org/repos/asf/superset.git


      at 59f36997cfc fix(reports): pre-commit tab permalinks before state machine transaction

This branch includes the following new commits:

     new 59f36997cfc fix(reports): pre-commit tab permalinks before state machine transaction

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(superset) 01/01: fix(reports): pre-commit tab permalinks before state machine transaction

Posted by el...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

eschutho pushed a commit to branch fix/report-tab-permalink-pre-commit
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 59f36997cfcc308a4baf8e1564d4f0b771f36d34
Author: Elizabeth Thompson <es...@gmail.com>
AuthorDate: Tue Jun 16 00:15:23 2026 +0000

    fix(reports): pre-commit tab permalinks before state machine transaction
    
    When a dashboard report targets specific tabs, BaseReportState calls
    CreateDashboardPermalinkCommand inside the outer @transaction() on
    AsyncExecuteReportScheduleCommand.run(). The @transaction() nesting guard
    (g.in_transaction) causes the command to only flush the permalink INSERT,
    leaving the row invisible to Playwright's separate DB connection. Flask
    returns a 404 from dashboard_permalink, <body class="standalone"> never
    appears, and the screenshot times out after 600 s.
    
    Fix: remove @transaction() from AsyncExecuteReportScheduleCommand.run()
    and add a pre-warm call to get_dashboard_urls() before the state machine
    starts. Executed outside any transaction, the call lets
    CreateDashboardPermalinkCommand commit normally via its own @transaction().
    The state machine's subsequent call to get_dashboard_urls() finds the
    already-committed row through get_entry() (same deterministic UUID) and
    returns it without a second INSERT. ReportScheduleStateMachine.run()
    retains its own @transaction() and remains the outermost transaction owner.
    
    Co-Authored-By: Claude Sonnet 4.6 <no...@anthropic.com>
---
 superset/commands/report/execute.py | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/superset/commands/report/execute.py b/superset/commands/report/execute.py
index fa5fb9422bd..ffc57e4cdb8 100644
--- a/superset/commands/report/execute.py
+++ b/superset/commands/report/execute.py
@@ -1157,7 +1157,6 @@ class AsyncExecuteReportScheduleCommand(BaseCommand):
         self._scheduled_dttm = scheduled_dttm
         self._execution_id = UUID(task_id)
 
-    @transaction()
     def run(self) -> None:
         try:
             self.validate()
@@ -1170,6 +1169,21 @@ class AsyncExecuteReportScheduleCommand(BaseCommand):
             )
             user = security_manager.find_user(username)
 
+            with override_user(user):
+                # Pre-commit any permalink rows before the state machine's
+                # @transaction() opens. When called inside a transaction,
+                # CreateDashboardPermalinkCommand only flushes (not commits),
+                # leaving the row invisible to Playwright's separate DB
+                # connection. Running get_dashboard_urls() here — outside any
+                # transaction — lets the command commit normally. The state
+                # machine's inner call to get_dashboard_urls() hits get_entry()
+                # for the same deterministic UUID and returns the
+                # already-committed row without a second INSERT.
+                if self._model.dashboard_id:
+                    BaseReportState(
+                        self._model, self._scheduled_dttm, self._execution_id
+                    ).get_dashboard_urls()
+
             start_time = datetime.utcnow()
             with override_user(user):
                 ReportScheduleStateMachine(