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


##########
indexing-service/src/main/java/org/apache/druid/indexing/overlord/hrtr/HttpRemoteTaskRunner.java:
##########
@@ -1123,6 +1144,17 @@ private void pendingTasksExecutionLoop()
               break;
             }
 
+            if (eligibleWorkers == null) {
+              eligibleWorkers = 
ImmutableMap.copyOf(getWorkersEligibleToRunTasks());
+            }
+
+            // Cheap pre-filter against the reused snapshot: skip tasks that 
clearly have no worker.
+            if (findWorkerToRunTask(ti.getTask(), eligibleWorkers) == null) {
+              continue;
+            }
+
+            // A candidate exists in the snapshot; re-select against a fresh 
snapshot before
+            // reserving so the assignment reflects current worker capacity 
(see comment above).
             immutableWorker = findWorkerToRunTask(ti.getTask());

Review Comment:
   [P2] Revalidate capacity atomically with reservation
   
   **Finding:** This fresh selection is still not atomic with the reservation 
below it. WorkerHolder can publish a new task announcement into 
tasksSnapshotRef without statusLock, so a worker can become full after this 
call returns but before workersWithUnacknowledgedTask.putIfAbsent runs. The 
selected ImmutableWorkerInfo is then stale, and runTaskOnWorker only checks 
removal/lazy/blacklist before posting /assignTask, allowing an oversubscribing 
assignment for a worker whose capacity changed in that window.
   
   **Suggestion:** Make capacity publication, the capacity check, and the 
reservation atomic, or revalidate the selected worker immediately before or 
inside assignment, and add a regression test for an announcement arriving 
between selection and reservation.



##########
indexing-service/src/main/java/org/apache/druid/indexing/overlord/hrtr/HttpRemoteTaskRunner.java:
##########
@@ -1123,6 +1144,17 @@ private void pendingTasksExecutionLoop()
               break;
             }
 
+            if (eligibleWorkers == null) {
+              eligibleWorkers = 
ImmutableMap.copyOf(getWorkersEligibleToRunTasks());
+            }
+
+            // Cheap pre-filter against the reused snapshot: skip tasks that 
clearly have no worker.
+            if (findWorkerToRunTask(ti.getTask(), eligibleWorkers) == null) {

Review Comment:
   [P2] Invalidate the cached snapshot after a failed refresh
   
   **Finding:** If the cached pre-filter snapshot contains a candidate but the 
fresh selection at line 1158 returns null because that worker became 
unavailable, eligibleWorkers remains unchanged and the loop continues. Every 
remaining pending task then passes the stale pre-filter and calls 
findWorkerToRunTask(task) again, rebuilding the full worker/task-announcement 
snapshot while holding statusLock. A capacity or state change during a large 
backlog can therefore reproduce the original O(pendingTasks x workers x 
tasksAnnouncedPerWorker) lock stall.
   
   **Suggestion:** Refresh or replace the cached pre-filter snapshot after a 
fresh selection returns no worker, or stop the pass and wait for the 
worker-state notification instead of repeating the expensive refresh for every 
pending task.



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