|
21 | 21 | import org.apache.flink.api.common.ExecutionConfig; |
22 | 22 | import org.apache.flink.runtime.JobException; |
23 | 23 | import org.apache.flink.runtime.concurrent.ComponentMainThreadExecutor; |
24 | | -import org.apache.flink.runtime.concurrent.ComponentMainThreadExecutorServiceAdapter; |
25 | 24 | import org.apache.flink.runtime.execution.ExecutionState; |
26 | 25 | import org.apache.flink.runtime.executiongraph.AccessExecutionJobVertex; |
27 | 26 | import org.apache.flink.runtime.executiongraph.Execution; |
|
46 | 45 | import org.apache.flink.runtime.scheduler.strategy.VertexwiseSchedulingStrategy; |
47 | 46 | import org.apache.flink.runtime.taskmanager.TaskExecutionState; |
48 | 47 | import org.apache.flink.runtime.testtasks.NoOpInvokable; |
| 48 | +import org.apache.flink.runtime.testutils.DirectScheduledExecutorService; |
49 | 49 | import org.apache.flink.util.concurrent.ScheduledExecutorServiceAdapter; |
50 | 50 |
|
51 | 51 | import java.io.IOException; |
52 | 52 | import java.util.ArrayList; |
53 | 53 | import java.util.Collections; |
54 | 54 | import java.util.List; |
| 55 | +import java.util.concurrent.Callable; |
55 | 56 | import java.util.concurrent.ExecutionException; |
56 | 57 | import java.util.concurrent.ScheduledExecutorService; |
| 58 | +import java.util.concurrent.ScheduledFuture; |
| 59 | +import java.util.concurrent.TimeUnit; |
57 | 60 |
|
58 | 61 | import static org.apache.flink.runtime.scheduler.DefaultSchedulerBuilder.createCustomParallelismDecider; |
59 | 62 | import static org.apache.flink.runtime.scheduler.adaptivebatch.AdaptiveBatchSchedulerFactory.loadInputConsumableDeciderFactory; |
@@ -110,8 +113,11 @@ public static DefaultScheduler createAndInitScheduler( |
110 | 113 |
|
111 | 114 | final JobGraph jobGraph = createJobGraph(jobVertices, jobConfiguration); |
112 | 115 |
|
| 116 | + // Use a synchronous executor without strict thread identity checks to avoid |
| 117 | + // assertion failures when CompletableFuture callbacks from async TDD creation |
| 118 | + // in deploy() are dispatched from background threads. |
113 | 119 | final ComponentMainThreadExecutor mainThreadExecutor = |
114 | | - ComponentMainThreadExecutorServiceAdapter.forMainThread(); |
| 120 | + new SynchronousComponentMainThreadExecutor(); |
115 | 121 |
|
116 | 122 | DefaultSchedulerBuilder schedulerBuilder = |
117 | 123 | new DefaultSchedulerBuilder(jobGraph, mainThreadExecutor, scheduledExecutorService) |
@@ -223,4 +229,50 @@ public static void transitionTaskStatus( |
223 | 229 | vertex.getTaskVertices()[subtask].getCurrentExecutionAttempt().getAttemptId(); |
224 | 230 | scheduler.updateTaskExecutionState(new TaskExecutionState(attemptId, executionState)); |
225 | 231 | } |
| 232 | + |
| 233 | + /** |
| 234 | + * A synchronous {@link ComponentMainThreadExecutor} that executes tasks directly on the calling |
| 235 | + * thread. |
| 236 | + * |
| 237 | + * <p>Unlike {@link ComponentMainThreadExecutorServiceAdapter#forMainThread()}, this executor |
| 238 | + * does not perform strict thread identity checks, avoiding flaky test failures when |
| 239 | + * CompletableFuture callbacks are dispatched from background threads. |
| 240 | + */ |
| 241 | + private static class SynchronousComponentMainThreadExecutor |
| 242 | + implements ComponentMainThreadExecutor { |
| 243 | + private final DirectScheduledExecutorService executor = |
| 244 | + new DirectScheduledExecutorService(); |
| 245 | + |
| 246 | + @Override |
| 247 | + public void assertRunningInMainThread() { |
| 248 | + // No-op: Skip thread assertion to avoid flaky test failures |
| 249 | + } |
| 250 | + |
| 251 | + @Override |
| 252 | + public void execute(Runnable command) { |
| 253 | + executor.execute(command); |
| 254 | + } |
| 255 | + |
| 256 | + @Override |
| 257 | + public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) { |
| 258 | + return executor.schedule(command, delay, unit); |
| 259 | + } |
| 260 | + |
| 261 | + @Override |
| 262 | + public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) { |
| 263 | + return executor.schedule(callable, delay, unit); |
| 264 | + } |
| 265 | + |
| 266 | + @Override |
| 267 | + public ScheduledFuture<?> scheduleAtFixedRate( |
| 268 | + Runnable command, long initialDelay, long period, TimeUnit unit) { |
| 269 | + return executor.scheduleAtFixedRate(command, initialDelay, period, unit); |
| 270 | + } |
| 271 | + |
| 272 | + @Override |
| 273 | + public ScheduledFuture<?> scheduleWithFixedDelay( |
| 274 | + Runnable command, long initialDelay, long delay, TimeUnit unit) { |
| 275 | + return executor.scheduleWithFixedDelay(command, initialDelay, delay, unit); |
| 276 | + } |
| 277 | + } |
226 | 278 | } |
0 commit comments