1515 * limitations under the License.
1616 */
1717
18- package org .apache .dolphinscheduler .server .master .runner ;
18+ package org .apache .dolphinscheduler .server .master .engine . task . dispatcher ;
1919
2020import org .apache .dolphinscheduler .common .thread .BaseDaemonThread ;
21- import org .apache .dolphinscheduler .dao .entity .TaskInstance ;
22- import org .apache .dolphinscheduler .plugin .task .api .enums .TaskExecutionStatus ;
2321import org .apache .dolphinscheduler .server .master .engine .task .client .ITaskExecutorClient ;
2422import org .apache .dolphinscheduler .server .master .engine .task .runnable .ITaskExecutionRunnable ;
2523import org .apache .dolphinscheduler .server .master .runner .queue .PriorityAndDelayBasedTaskEntry ;
2624import org .apache .dolphinscheduler .server .master .runner .queue .PriorityDelayQueue ;
25+ import org .apache .dolphinscheduler .task .executor .log .TaskExecutorMDCUtils ;
2726
27+ import java .util .Set ;
28+ import java .util .concurrent .ConcurrentHashMap ;
2829import java .util .concurrent .atomic .AtomicBoolean ;
2930
3031import lombok .extern .slf4j .Slf4j ;
3738 * 3. Ensuring thread safety and correct state transitions during task processing.
3839 */
3940@ Slf4j
40- public class WorkerGroupTaskDispatcher extends BaseDaemonThread {
41+ public class WorkerGroupDispatcher extends BaseDaemonThread {
4142
4243 private final ITaskExecutorClient taskExecutorClient ;
4344
@@ -47,26 +48,16 @@ public class WorkerGroupTaskDispatcher extends BaseDaemonThread {
4748 // If it needs to be placed at the front of the queue, the queue needs to be re-implemented.
4849 private final PriorityDelayQueue <PriorityAndDelayBasedTaskEntry <ITaskExecutionRunnable >> workerGroupQueue ;
4950
51+ private final Set <Integer > waitingDispatchTaskIds ;
52+
5053 private final AtomicBoolean runningFlag = new AtomicBoolean (false );
5154
52- public WorkerGroupTaskDispatcher (String workerGroupName , ITaskExecutorClient taskExecutorClient ) {
55+ public WorkerGroupDispatcher (String workerGroupName , ITaskExecutorClient taskExecutorClient ) {
5356 super ("WorkerGroupTaskDispatcher-" + workerGroupName );
5457 this .taskExecutorClient = taskExecutorClient ;
5558 this .workerGroupQueue = new PriorityDelayQueue <>();
56- }
57-
58- /**
59- * Adds a task to the worker group queue.
60- * This method wraps the given task execution object into a priority and delay-based task entry and adds it to the worker group queue.
61- * The task is only added if the current dispatcher status is either STARTED or INIT. If the dispatcher is in any other state,
62- * the task addition will fail, and a warning message will be logged.
63- *
64- * @param taskExecutionRunnable The task execution object to add to the queue, which implements the {@link ITaskExecutionRunnable} interface.
65- * @param delayTimeMills The delay time in milliseconds before the task should be executed.
66- */
67- public void addTaskToWorkerGroupQueue (ITaskExecutionRunnable taskExecutionRunnable ,
68- long delayTimeMills ) {
69- workerGroupQueue .add (new PriorityAndDelayBasedTaskEntry <>(delayTimeMills , taskExecutionRunnable ));
59+ this .waitingDispatchTaskIds = ConcurrentHashMap .newKeySet ();
60+ log .info ("Initialize WorkerGroupDispatcher: {}" , this .getName ());
7061 }
7162
7263 @ Override
@@ -80,27 +71,25 @@ public synchronized void start() {
8071 }
8172 }
8273
83- public synchronized void close () {
84- log .info ("The {} closed called but not implemented" , this .getName ());
85- // todo WorkerGroupTaskDispatcher thread needs to be shut down after the WorkerGroup is deleted.
86- }
87-
8874 @ Override
8975 public void run () {
9076 while (runningFlag .get ()) {
91- dispatch ();
77+ PriorityAndDelayBasedTaskEntry <ITaskExecutionRunnable > taskEntry = workerGroupQueue .take ();
78+ ITaskExecutionRunnable taskExecutionRunnable = taskEntry .getData ();
79+ try (
80+ TaskExecutorMDCUtils .MDCAutoClosable ignore =
81+ TaskExecutorMDCUtils .logWithMDC (taskExecutionRunnable .getId ())) {
82+ doDispatchTask (taskExecutionRunnable );
83+ }
9284 }
9385 }
9486
95- private void dispatch () {
96- PriorityAndDelayBasedTaskEntry <ITaskExecutionRunnable > taskEntry = workerGroupQueue .take ();
97- ITaskExecutionRunnable taskExecutionRunnable = taskEntry .getData ();
98- final TaskInstance taskInstance = taskExecutionRunnable .getTaskInstance ();
87+ private void doDispatchTask (ITaskExecutionRunnable taskExecutionRunnable ) {
9988 try {
100- final TaskExecutionStatus taskStatus = taskInstance . getState ();
101- if ( taskStatus != TaskExecutionStatus . SUBMITTED_SUCCESS
102- && taskStatus != TaskExecutionStatus . DELAY_EXECUTION ) {
103- log . warn ( "The TaskInstance {} state is : {}, will not dispatch" , taskInstance . getName (), taskStatus );
89+ if (! waitingDispatchTaskIds . remove ( taskExecutionRunnable . getId ())) {
90+ log . info (
91+ "The task: {} doesn't exist in waitingDispatchTaskIds(it might be paused or killed), will skip dispatch" ,
92+ taskExecutionRunnable . getId () );
10493 return ;
10594 }
10695 taskExecutorClient .dispatch (taskExecutionRunnable );
@@ -110,16 +99,44 @@ private void dispatch() {
11099 // the waiting time will increase multiple of times, but will not exceed 60 seconds
111100 long waitingTimeMills = Math .min (
112101 taskExecutionRunnable .getTaskExecutionContext ().increaseDispatchFailTimes () * 1_000L , 60_000L );
113- workerGroupQueue .add (new PriorityAndDelayBasedTaskEntry <>(waitingTimeMills , taskExecutionRunnable ));
114- log .error ("Dispatch Task: {} failed will retry after: {}/ms" , taskInstance .getName (), waitingTimeMills , e );
102+ dispatchTask (taskExecutionRunnable , waitingTimeMills );
103+ log .error ("Dispatch Task: {} failed will retry after: {}/ms" , taskExecutionRunnable .getId (),
104+ waitingTimeMills , e );
115105 }
116106 }
117107
118108 /**
119- * ony use unit test
120- * @return size
109+ * Adds a task to the worker group queue.
110+ * This method wraps the given task execution object into a priority and delay-based task entry and adds it to the worker group queue.
111+ * The task is only added if the current dispatcher status is either STARTED or INIT. If the dispatcher is in any other state,
112+ * the task addition will fail, and a warning message will be logged.
113+ *
114+ * @param taskExecutionRunnable The task execution object to add to the queue, which implements the {@link ITaskExecutionRunnable} interface.
115+ * @param delayTimeMills The delay time in milliseconds before the task should be executed.
121116 */
122- protected int queueSize () {
117+ public void dispatchTask (final ITaskExecutionRunnable taskExecutionRunnable , final long delayTimeMills ) {
118+ waitingDispatchTaskIds .add (taskExecutionRunnable .getId ());
119+ workerGroupQueue .add (new PriorityAndDelayBasedTaskEntry <>(delayTimeMills , taskExecutionRunnable ));
120+ }
121+
122+ public boolean removeTask (ITaskExecutionRunnable taskExecutionRunnable ) {
123+ return waitingDispatchTaskIds .remove (taskExecutionRunnable .getId ());
124+ }
125+
126+ public boolean existTask (ITaskExecutionRunnable taskExecutionRunnable ) {
127+ return waitingDispatchTaskIds .contains (taskExecutionRunnable .getId ());
128+ }
129+
130+ public synchronized void close () {
131+ // todo WorkerGroupTaskDispatcher thread needs to be shut down after the WorkerGroup is deleted.
132+ if (runningFlag .compareAndSet (true , false )) {
133+ log .info ("WorkerGroupDispatcher {} closed" , this .getName ());
134+ } else {
135+ log .warn ("The WorkerGroupDispatcher: {} doesn't started" , this .getName ());
136+ }
137+ }
138+
139+ int queueSize () {
123140 return this .workerGroupQueue .size ();
124141 }
125142}
0 commit comments