Skip to content

Commit

Permalink
Scheduler: document @Scheduled#executionMaxDelay()
Browse files Browse the repository at this point in the history
- also add test for JobDefinition#setExecutionMaxDelay()
  • Loading branch information
mkouba committed Sep 27, 2024
1 parent 03e46f6 commit 129b98b
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 11 deletions.
28 changes: 24 additions & 4 deletions docs/src/main/asciidoc/scheduler-reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,8 @@ Property Expressions. (Note that `"{property.path}"` style expressions are still
void myMethod() { }
----

=== Delayed Execution
[[delayed_start]]
=== Delayed Start of a Trigger

`@Scheduled` provides two ways to delay the time a trigger should start firing at.

Expand Down Expand Up @@ -249,9 +250,8 @@ void everyTwoSeconds() { }
NOTE: If `@Scheduled#delay()` is set to a value greater than zero the value of `@Scheduled#delayed()` is ignored.

The main advantage over `@Scheduled#delay()` is that the value is configurable.
The `delay` attribute supports <<config-reference#property-expressions,Property Expressions>> including default values and nested
Property Expressions. (Note that `"{property.path}"` style expressions are still supported but don't offer the full functionality of Property Expressions.)

The `delay` attribute supports <<config-reference#property-expressions,Property Expressions>> including default values and nested Property Expressions.
(Note that `"{property.path}"` style expressions are still supported but don't offer the full functionality of Property Expressions.)

[source,java]
----
Expand All @@ -260,6 +260,26 @@ void everyTwoSeconds() { }
----
<1> The config property `myMethod.delay.expr` is used to set the delay.

[[delayed_execution]]
=== Delayed Execution

`@Scheduled#executionMaxDelay()` can be set to delay each execution of a scheduled method.
The value represents the maximum delay between the activation of the trigger and the execution of the scheduled method.
The actual delay varies randomly over time but it never exceeds the maximum value.

The value is parsed with `DurationConverter#parseDuration(String)`.
It can be a property expression.
In that case, the scheduler attempts to use the configured value instead: `@Scheduled(executionMaxDelay = "${myJob.maxDelay}")`.
Additionally, the property expression can specify a default value:
`@Scheduled(executionMaxDelay = "${myJob.maxDelay}:500ms}")`.

[source,java]
----
@Scheduled(every = "2s", executionMaxDelay = "500ms") <1>
void everyTwoSeconds() { }
----
<1> The delay will be a value between 0 and 500 milliseconds. As a result, the period between to `everyTwoSeconds()` executions will be roughly between two and two and a half seconds.

[[concurrent_execution]]
=== Concurrent Execution

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.quarkus.scheduler.test.delayedexecution;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.concurrent.CountDownLatch;
Expand All @@ -11,8 +10,10 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.runtime.StartupEvent;
import io.quarkus.scheduler.DelayedExecution;
import io.quarkus.scheduler.Scheduled;
import io.quarkus.scheduler.Scheduler;
import io.quarkus.test.QuarkusUnitTest;

public class DelayedExecutionTest {
Expand All @@ -24,23 +25,38 @@ public class DelayedExecutionTest {
@Test
public void testSimpleScheduledJobs() throws InterruptedException {
assertTrue(Jobs.EVENT_LATCH.await(5, TimeUnit.SECONDS));
assertTrue(Jobs.LATCH.await(5, TimeUnit.SECONDS));
assertTrue(Jobs.LATCH1.await(5, TimeUnit.SECONDS));
assertTrue(Jobs.LATCH2.await(5, TimeUnit.SECONDS));
}

static class Jobs {

static final CountDownLatch LATCH = new CountDownLatch(1);
static final CountDownLatch EVENT_LATCH = new CountDownLatch(1);
static final CountDownLatch LATCH1 = new CountDownLatch(1);
static final CountDownLatch LATCH2 = new CountDownLatch(1);
static final CountDownLatch EVENT_LATCH = new CountDownLatch(2);

@Scheduled(identity = "foo", every = "1s", executionMaxDelay = "500ms")
static void everySecond() {
LATCH.countDown();
LATCH1.countDown();
}

void start(@Observes StartupEvent event, Scheduler scheduler) {
scheduler.newJob("bar")
.setInterval("1s")
.setExecutionMaxDelay("500ms")
.setTask(se -> {
LATCH2.countDown();
}).schedule();
}

void onDelay(@Observes DelayedExecution delayedExecution) {
assertTrue(delayedExecution.getDelay() < 500);
assertEquals("foo", delayedExecution.getExecution().getTrigger().getId());
EVENT_LATCH.countDown();
String id = delayedExecution.getExecution().getTrigger().getId();
if ("foo".equals(id) || "bar".equals(id)) {
EVENT_LATCH.countDown();
} else {
throw new IllegalStateException("Invalid job identity: " + id);
}
}

}
Expand Down

0 comments on commit 129b98b

Please sign in to comment.