FrankChen021 commented on code in PR #20293:
URL: https://github.com/apache/druid/pull/20293#discussion_r4024175561


##########
multi-stage-query/src/main/java/org/apache/druid/msq/exec/ControllerHolder.java:
##########
@@ -185,11 +209,22 @@ public ListenableFuture<?> runAsync(
               }
             }
 
-            updateStateOnQueryComplete(reportListener.getReport());
+            reportMap = controller.finalReport();
+            if (reportMap != null) {
+              final TaskReport taskReport = 
reportMap.get(MSQTaskReport.REPORT_KEY);
+              if (taskReport instanceof MSQTaskReport) {
+                final MSQTaskReportPayload report = ((MSQTaskReport) 
taskReport).getPayload();
+                if (report != null) {
+                  updateStateOnQueryComplete(report);
+                }
+              }
+            }
           } else {
             // Canceled before running.
+            final MSQTaskReportPayload canceledReport = 
makeCanceledReport(cancelReason);
+            reportMap = TaskReport.buildTaskReports(new 
MSQTaskReport(controller.queryId(), canceledReport));
             synchronized (this) {
-              reportListener.onQueryComplete(makeCanceledReport(cancelReason));
+              listener.onQueryComplete(canceledReport);

Review Comment:
   Fixed in `1fa600454a`. The pre-run cancellation branch now snapshots the 
canceled report under the holder lock and invokes `onQueryComplete` after 
releasing it, allowing `getReports()` to acquire the lock while the callback is 
still running. The regression test now performs the registry lookup on a 
separate controller-pool thread and requires it to complete before releasing 
the callback. Focused validation: 24 tests passed with 0 failures or errors.



##########
multi-stage-query/src/main/java/org/apache/druid/msq/exec/ControllerHolder.java:
##########
@@ -169,7 +181,15 @@ public ListenableFuture<?> runAsync(
       Thread.currentThread().setName(makeThreadName());
 
       try {
-        final CaptureReportQueryListener reportListener = new 
CaptureReportQueryListener(listener);
+        final CaptureReportQueryListener reportListener = new 
CaptureReportQueryListener(listener)
+        {
+          @Override
+          public void onQueryComplete(final MSQTaskReportPayload report)
+          {
+            finalReport = TaskReport.buildTaskReports(new 
MSQTaskReport(controller.queryId(), report));

Review Comment:
   Thanks, understood that returning the final report from `/liveReports` would 
be acceptable. I kept `liveReports()` and `finalReport()` separate in this PR 
so the live-snapshot API and the final-only publication signal remain explicit, 
and so this concurrency fix does not also change the endpoint contract. The 
duplicate `CaptureReportQueryListener` capture has still been removed; the 
final report is retained only by `ControllerImpl`.



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