|
1 | 1 | /*
|
2 |
| - * Copyright 2012-2023 the original author or authors. |
| 2 | + * Copyright 2012-2024 the original author or authors. |
3 | 3 | *
|
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
5 | 5 | * you may not use this file except in compliance with the License.
|
|
16 | 16 | package org.springframework.batch.core.job.builder;
|
17 | 17 |
|
18 | 18 | import java.util.Arrays;
|
| 19 | +import java.util.concurrent.CountDownLatch; |
| 20 | +import java.util.concurrent.TimeUnit; |
19 | 21 |
|
20 | 22 | import javax.sql.DataSource;
|
21 | 23 |
|
22 | 24 | import static org.junit.jupiter.api.Assertions.assertEquals;
|
23 | 25 |
|
| 26 | +import org.junit.jupiter.api.Assertions; |
24 | 27 | import org.junit.jupiter.api.BeforeEach;
|
25 | 28 | import org.junit.jupiter.api.Test;
|
26 | 29 | import org.springframework.batch.core.BatchStatus;
|
|
45 | 48 | import org.springframework.batch.core.step.StepSupport;
|
46 | 49 | import org.springframework.batch.core.step.builder.StepBuilder;
|
47 | 50 | import org.springframework.batch.item.support.ListItemReader;
|
| 51 | +import org.springframework.batch.repeat.RepeatStatus; |
| 52 | +import org.springframework.batch.support.transaction.ResourcelessTransactionManager; |
48 | 53 | import org.springframework.beans.factory.annotation.Value;
|
49 | 54 | import org.springframework.context.ApplicationContext;
|
50 | 55 | import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
@@ -369,4 +374,38 @@ public JdbcTransactionManager transactionManager(DataSource dataSource) {
|
369 | 374 |
|
370 | 375 | }
|
371 | 376 |
|
| 377 | + @Test |
| 378 | + public void testBuildSplitWithParallelFlow() throws InterruptedException { |
| 379 | + CountDownLatch countDownLatch = new CountDownLatch(1); |
| 380 | + Step longExecutingStep = new StepBuilder("longExecutingStep", jobRepository).tasklet((stepContribution, b) -> { |
| 381 | + Thread.sleep(500L); |
| 382 | + return RepeatStatus.FINISHED; |
| 383 | + }, new ResourcelessTransactionManager()).build(); |
| 384 | + |
| 385 | + Step interruptedStep = new StepBuilder("interruptedStep", jobRepository).tasklet((stepContribution, b) -> { |
| 386 | + stepContribution.getStepExecution().setTerminateOnly(); |
| 387 | + return RepeatStatus.FINISHED; |
| 388 | + }, new ResourcelessTransactionManager()).build(); |
| 389 | + |
| 390 | + Step nonExecutableStep = new StepBuilder("nonExecutableStep", jobRepository).tasklet((stepContribution, b) -> { |
| 391 | + countDownLatch.countDown(); |
| 392 | + return RepeatStatus.FINISHED; |
| 393 | + }, new ResourcelessTransactionManager()).build(); |
| 394 | + |
| 395 | + Flow twoStepFlow = new FlowBuilder<SimpleFlow>("twoStepFlow").start(longExecutingStep) |
| 396 | + .next(nonExecutableStep) |
| 397 | + .build(); |
| 398 | + Flow interruptedFlow = new FlowBuilder<SimpleFlow>("interruptedFlow").start(interruptedStep).build(); |
| 399 | + |
| 400 | + Flow splitFlow = new FlowBuilder<Flow>("splitFlow").split(new SimpleAsyncTaskExecutor()) |
| 401 | + .add(interruptedFlow, twoStepFlow) |
| 402 | + .build(); |
| 403 | + FlowJobBuilder jobBuilder = new JobBuilder("job", jobRepository).start(splitFlow).build(); |
| 404 | + jobBuilder.preventRestart().build().execute(execution); |
| 405 | + |
| 406 | + boolean isExecutedNonExecutableStep = countDownLatch.await(1, TimeUnit.SECONDS); |
| 407 | + assertEquals(BatchStatus.STOPPED, execution.getStatus()); |
| 408 | + Assertions.assertFalse(isExecutedNonExecutableStep); |
| 409 | + } |
| 410 | + |
372 | 411 | }
|
0 commit comments