Support for one-time tasks with just @Scheduled(initialDelay=...)

Closes gh-31211
This commit is contained in:
Juergen Hoeller
2023-09-13 16:48:54 +02:00
parent e63e3a6d28
commit 8f6c56fe9a
10 changed files with 321 additions and 79 deletions

View File

@@ -218,15 +218,6 @@ public class EnableSchedulingTests {
assertThat(ctx.getBean(ThreadAwareWorker.class).executedByThread).startsWith("taskScheduler-");
}
@Test
@EnabledForTestGroups(LONG_RUNNING)
public void withTriggerTask() throws InterruptedException {
ctx = new AnnotationConfigApplicationContext(TriggerTaskConfig.class);
Thread.sleep(110);
assertThat(ctx.getBean(AtomicInteger.class).get()).isGreaterThan(1);
}
@Test
@EnabledForTestGroups(LONG_RUNNING)
public void withInitiallyDelayedFixedRateTask() throws InterruptedException {
@@ -235,9 +226,30 @@ public class EnableSchedulingTests {
Thread.sleep(1950);
AtomicInteger counter = ctx.getBean(AtomicInteger.class);
// The @Scheduled method should have been called at least once but
// not more times than the delay allows.
assertThat(counter.get()).isBetween(1, 10);
// The @Scheduled method should have been called several times
// but not more times than the delay allows.
assertThat(counter.get()).isBetween(2, 10);
}
@Test
@EnabledForTestGroups(LONG_RUNNING)
public void withOneTimeTask() throws InterruptedException {
ctx = new AnnotationConfigApplicationContext(OneTimeTaskConfig.class);
Thread.sleep(110);
AtomicInteger counter = ctx.getBean(AtomicInteger.class);
// The @Scheduled method should have been called exactly once.
assertThat(counter.get()).isEqualTo(1);
}
@Test
@EnabledForTestGroups(LONG_RUNNING)
public void withTriggerTask() throws InterruptedException {
ctx = new AnnotationConfigApplicationContext(TriggerTaskConfig.class);
Thread.sleep(110);
assertThat(ctx.getBean(AtomicInteger.class).get()).isGreaterThan(1);
}
@@ -598,6 +610,38 @@ public class EnableSchedulingTests {
}
@Configuration
@EnableScheduling
static class FixedRateTaskConfig_withInitialDelay {
@Bean
public AtomicInteger counter() {
return new AtomicInteger();
}
@Scheduled(initialDelay = 1000, fixedRate = 100)
public void task() {
counter().incrementAndGet();
}
}
@Configuration
@EnableScheduling
static class OneTimeTaskConfig {
@Bean
public AtomicInteger counter() {
return new AtomicInteger();
}
@Scheduled(initialDelay = 10)
public void task() {
counter().incrementAndGet();
}
}
@Configuration
static class TriggerTaskConfig {
@@ -616,20 +660,4 @@ public class EnableSchedulingTests {
}
}
@Configuration
@EnableScheduling
static class FixedRateTaskConfig_withInitialDelay {
@Bean
public AtomicInteger counter() {
return new AtomicInteger();
}
@Scheduled(initialDelay = 1000, fixedRate = 100)
public void task() {
counter().incrementAndGet();
}
}
}

View File

@@ -57,6 +57,7 @@ import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.config.CronTask;
import org.springframework.scheduling.config.IntervalTask;
import org.springframework.scheduling.config.OneTimeTask;
import org.springframework.scheduling.config.ScheduledTaskHolder;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
@@ -266,6 +267,33 @@ class ScheduledAnnotationBeanPostProcessorTests {
assertThat(task2.getIntervalDuration()).isEqualTo(Duration.ofMillis(4_000L));
}
@Test
void oneTimeTask() {
BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class);
BeanDefinition targetDefinition = new RootBeanDefinition(OneTimeTaskBean.class);
context.registerBeanDefinition("postProcessor", processorDefinition);
context.registerBeanDefinition("target", targetDefinition);
context.refresh();
ScheduledTaskHolder postProcessor = context.getBean("postProcessor", ScheduledTaskHolder.class);
assertThat(postProcessor.getScheduledTasks()).hasSize(1);
Object target = context.getBean("target");
ScheduledTaskRegistrar registrar = (ScheduledTaskRegistrar)
new DirectFieldAccessor(postProcessor).getPropertyValue("registrar");
@SuppressWarnings("unchecked")
List<OneTimeTask> oneTimeTasks = (List<OneTimeTask>)
new DirectFieldAccessor(registrar).getPropertyValue("oneTimeTasks");
assertThat(oneTimeTasks).hasSize(1);
OneTimeTask task = oneTimeTasks.get(0);
ScheduledMethodRunnable runnable = (ScheduledMethodRunnable) task.getRunnable();
Object targetObject = runnable.getTarget();
Method targetMethod = runnable.getMethod();
assertThat(targetObject).isEqualTo(target);
assertThat(targetMethod.getName()).isEqualTo("oneTimeTask");
assertThat(task.getInitialDelayDuration()).isEqualTo(Duration.ofMillis(2_000L));
}
@Test
void cronTask() {
BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class);
@@ -848,6 +876,14 @@ class ScheduledAnnotationBeanPostProcessorTests {
}
static class OneTimeTaskBean {
@Scheduled(initialDelay = 2_000)
private void oneTimeTask() {
}
}
@Validated
static class CronTestBean {